Skip to content

Commit 2ba5799

Browse files
Add better entity exclusion
Signed-off-by: Aleksander Kamiński <[email protected]>
1 parent 7ec6a2f commit 2ba5799

File tree

8 files changed

+246
-5
lines changed

8 files changed

+246
-5
lines changed

Code/Include/RGL/RGLBus.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ namespace RGL
3636
//! Updates scene to the RGL
3737
virtual void UpdateScene() = 0;
3838

39+
//! Forces a reevaluation of entity presence conditions.
40+
//! Results of this condition reevaluation influence entity's inclusion in raycasting.
41+
virtual void ReviseEntityPresence(AZ::EntityId entityId) = 0;
42+
3943
protected:
4044
~RGLRequests() = default;
4145
};

Code/Include/RGL/SceneConfiguration.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
#include <Atom/RPI.Reflect/Image/StreamingImageAsset.h>
1818
#include <AzCore/Asset/AssetCommon.h>
19+
#include <AzCore/std/containers/vector.h>
20+
#include <AzCore/std/string/string.h>
1921

2022
namespace RGL
2123
{
@@ -37,6 +39,7 @@ namespace RGL
3739
static void Reflect(AZ::ReflectContext* context);
3840

3941
TerrainIntensityConfiguration m_terrainIntensityConfig;
42+
AZStd::vector<AZStd::string> m_excludedTagNames;
4043
// clang-format off
4144
bool m_isSkinnedMeshUpdateEnabled{ true }; //!< If set to true, all skinned meshes will be updated. Otherwise they will remain unchanged.
4245
// clang-format on
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/* Copyright 2024, Robotec.ai sp. z o.o.
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
#include <Entity/EntityTagListener.h>
16+
#include <RGL/RGLBus.h>
17+
18+
namespace RGL
19+
{
20+
EntityTagListener::EntityTagListener(AZ::EntityId entityId)
21+
: m_entityId(entityId)
22+
{
23+
AZ::EntityBus::Handler::BusConnect(m_entityId);
24+
}
25+
26+
EntityTagListener::~EntityTagListener()
27+
{
28+
AZ::EntityBus::Handler::BusDisconnect(m_entityId);
29+
}
30+
31+
void EntityTagListener::OnEntityActivated([[maybe_unused]] const AZ::EntityId& entityId)
32+
{
33+
LmbrCentral::Tags entityTags;
34+
LmbrCentral::TagComponentRequestBus::EventResult(entityTags, m_entityId, &LmbrCentral::TagComponentRequests::GetTags);
35+
36+
if (!entityTags.empty())
37+
{
38+
RGLInterface::Get()->ReviseEntityPresence(m_entityId);
39+
}
40+
41+
LmbrCentral::TagComponentNotificationsBus::Handler::BusConnect(m_entityId);
42+
}
43+
44+
void EntityTagListener::OnEntityDeactivated(const AZ::EntityId& entity_id)
45+
{
46+
LmbrCentral::TagComponentNotificationsBus::Handler::BusDisconnect(m_entityId);
47+
}
48+
49+
void EntityTagListener::OnTagAdded(const LmbrCentral::Tag& crc32)
50+
{
51+
RGLInterface::Get()->ReviseEntityPresence(m_entityId);
52+
}
53+
54+
void EntityTagListener::OnTagRemoved(const LmbrCentral::Tag& crc32)
55+
{
56+
RGLInterface::Get()->ReviseEntityPresence(m_entityId);
57+
}
58+
} // namespace RGL
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/* Copyright 2024, Robotec.ai sp. z o.o.
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
#pragma once
16+
17+
#include <AzCore/Component/EntityBus.h>
18+
#include <LmbrCentral/Scripting/TagComponentBus.h>
19+
20+
namespace RGL
21+
{
22+
class EntityTagListener
23+
: AZ::EntityBus::Handler
24+
, LmbrCentral::TagComponentNotificationsBus::Handler
25+
{
26+
public:
27+
EntityTagListener(AZ::EntityId entityId);
28+
~EntityTagListener();
29+
30+
void OnEntityActivated(const AZ::EntityId&) override;
31+
void OnEntityDeactivated(const AZ::EntityId&) override;
32+
33+
// TagComponentNotificationsBus overrides
34+
void OnTagAdded(const LmbrCentral::Tag&) override;
35+
void OnTagRemoved(const LmbrCentral::Tag&) override;
36+
37+
private:
38+
AZ::EntityId m_entityId;
39+
};
40+
} // namespace RGL

Code/Source/RGLSystemComponent.cpp

Lines changed: 115 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,15 @@ namespace RGL
8787

8888
AzFramework::EntityContextEventBus::Handler::BusConnect(gameEntityContextId);
8989
LidarSystemNotificationBus::Handler::BusConnect();
90+
AZ::TickBus::Handler::BusConnect();
9091

9192
m_rglLidarSystem.Activate();
9293
}
9394

9495
void RGLSystemComponent::Deactivate()
9596
{
9697
m_rglLidarSystem.Deactivate();
98+
AZ::TickBus::Handler::BusDisconnect();
9799
LidarSystemNotificationBus::Handler::BusDisconnect();
98100
AzFramework::EntityContextEventBus::Handler::BusDisconnect();
99101

@@ -113,6 +115,18 @@ namespace RGL
113115
void RGLSystemComponent::SetSceneConfiguration(const SceneConfiguration& config)
114116
{
115117
m_sceneConfig = config;
118+
119+
m_excludedTags.resize(config.m_excludedTagNames.size());
120+
AZStd::transform(
121+
config.m_excludedTagNames.begin(),
122+
config.m_excludedTagNames.end(),
123+
m_excludedTags.begin(),
124+
[](const AZStd::string& tagName) -> LmbrCentral::Tag
125+
{
126+
return LmbrCentral::Tag(tagName);
127+
});
128+
UpdateTagExcludedEntities();
129+
116130
RGLNotificationBus::Broadcast(&RGLNotifications::OnSceneConfigurationSet, config);
117131
}
118132

@@ -121,14 +135,37 @@ namespace RGL
121135
return m_sceneConfig;
122136
}
123137

138+
static bool HasExcludedTag(AZ::EntityId entityId, const AZStd::vector<LmbrCentral::Tag>& excludedTags)
139+
{
140+
LmbrCentral::Tags entityTags;
141+
LmbrCentral::TagComponentRequestBus::EventResult(entityTags, entityId, &LmbrCentral::TagComponentRequests::GetTags);
142+
143+
if (entityTags.empty())
144+
{
145+
return false;
146+
}
147+
148+
for (const auto tag : excludedTags)
149+
{
150+
if (entityTags.contains(tag))
151+
{
152+
return true;
153+
}
154+
}
155+
156+
return false;
157+
}
158+
124159
void RGLSystemComponent::OnEntityContextCreateEntity(AZ::Entity& entity)
125160
{
126-
if (m_excludedEntities.contains(entity.GetId()))
161+
if (!HasVisuals(entity))
127162
{
128163
return;
129164
}
130165

131-
if (m_activeLidarCount < 1U)
166+
m_entityTagListeners.emplace_back(entity.GetId());
167+
168+
if (m_activeLidarCount < 1U || ShouldEntityBeExcluded(entity.GetId()))
132169
{
133170
m_unprocessedEntities.emplace(entity.GetId());
134171
return;
@@ -163,6 +200,12 @@ namespace RGL
163200
RGLNotificationBus::Broadcast(&RGLNotifications::OnAnyLidarExists);
164201
for (auto entityIdIt = m_unprocessedEntities.begin(); entityIdIt != m_unprocessedEntities.end();)
165202
{
203+
if (ShouldEntityBeExcluded(*entityIdIt))
204+
{
205+
++entityIdIt;
206+
continue;
207+
}
208+
166209
AZ::Entity* entity = nullptr;
167210
AZ::ComponentApplicationBus::BroadcastResult(entity, &AZ::ComponentApplicationRequests::FindEntity, *entityIdIt);
168211
AZ_Assert(entity, "Failed to find entity with provided id!");
@@ -189,6 +232,26 @@ namespace RGL
189232
m_modelLibrary.Clear();
190233
}
191234

235+
void RGLSystemComponent::OnTick(float deltaTime, AZ::ScriptTimePoint time)
236+
{
237+
for (auto entityId : m_managersToBeRemoved)
238+
{
239+
m_entityManagers.erase(entityId);
240+
m_unprocessedEntities.insert(entityId);
241+
}
242+
m_managersToBeRemoved.clear();
243+
}
244+
245+
bool RGLSystemComponent::HasVisuals(const AZ::Entity& entity)
246+
{
247+
return entity.FindComponent<EMotionFX::Integration::ActorComponent>() || entity.FindComponent(AZ::Render::MeshComponentTypeId);
248+
}
249+
250+
bool RGLSystemComponent::ShouldEntityBeExcluded(AZ::EntityId entityId) const
251+
{
252+
return m_excludedEntities.contains(entityId) || HasExcludedTag(entityId, m_excludedTags);
253+
}
254+
192255
void RGLSystemComponent::ProcessEntity(const AZ::Entity& entity)
193256
{
194257
AZStd::unique_ptr<EntityManager> entityManager;
@@ -209,6 +272,27 @@ namespace RGL
209272
AZ_Error(__func__, inserted, "Object with provided entityId already exists.");
210273
}
211274

275+
void RGLSystemComponent::UpdateTagExcludedEntities()
276+
{
277+
if (m_excludedTags.empty())
278+
{
279+
return;
280+
}
281+
282+
for (auto entityManagerIt = m_entityManagers.begin(); entityManagerIt != m_entityManagers.end();)
283+
{
284+
if (HasExcludedTag(entityManagerIt->first, m_excludedTags))
285+
{
286+
m_unprocessedEntities.insert(entityManagerIt->first);
287+
entityManagerIt = m_entityManagers.erase(entityManagerIt);
288+
}
289+
else
290+
{
291+
++entityManagerIt;
292+
}
293+
}
294+
}
295+
212296
void RGLSystemComponent::UpdateScene()
213297
{
214298
AZ::ScriptTimePoint currentTime;
@@ -225,4 +309,33 @@ namespace RGL
225309
entityManager->Update();
226310
}
227311
}
312+
313+
void RGLSystemComponent::ReviseEntityPresence(AZ::EntityId entityId)
314+
{
315+
if (m_activeLidarCount < 1U)
316+
{
317+
return; // No lidars exist. Every entity should stay as unprocessed until they do.
318+
}
319+
320+
if (m_excludedEntities.contains(entityId))
321+
{
322+
return; // Already not included.
323+
}
324+
325+
if (HasExcludedTag(entityId, m_excludedTags))
326+
{
327+
if (m_entityManagers.contains(entityId))
328+
{
329+
m_managersToBeRemoved.push_back(entityId);
330+
}
331+
}
332+
else if (const auto it = m_unprocessedEntities.find(entityId); it != m_unprocessedEntities.end())
333+
{
334+
m_unprocessedEntities.erase(it);
335+
AZ::Entity* entity = nullptr;
336+
AZ::ComponentApplicationBus::BroadcastResult(entity, &AZ::ComponentApplicationRequests::FindEntity, entityId);
337+
AZ_Assert(entity, "Failed to find entity with provided id!");
338+
ProcessEntity(*entity);
339+
}
340+
}
228341
} // namespace RGL

Code/Source/RGLSystemComponent.h

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,14 @@
1515
#pragma once
1616

1717
#include <AzCore/Component/Component.h>
18+
#include <AzCore/Component/TickBus.h>
1819
#include <AzCore/Math/Vector3.h>
1920
#include <AzCore/Script/ScriptTimePoint.h>
2021
#include <AzFramework/Entity/EntityContextBus.h>
22+
#include <Entity/EntityTagListener.h>
2123
#include <Lidar/LidarSystem.h>
2224
#include <Lidar/LidarSystemNotificationBus.h>
25+
#include <LmbrCentral/Scripting/TagComponentBus.h>
2326
#include <Model/ModelLibrary.h>
2427
#include <RGL/RGLBus.h>
2528

@@ -32,6 +35,7 @@ namespace RGL
3235
, protected RGLRequestBus::Handler
3336
, protected AzFramework::EntityContextEventBus::Handler
3437
, protected LidarSystemNotificationBus::Handler
38+
, protected AZ::TickBus::Handler
3539
{
3640
public:
3741
AZ_COMPONENT(RGL::RGLSystemComponent, "{dbd5b1c5-249f-4eca-a142-2533ebe7f680}");
@@ -56,6 +60,7 @@ namespace RGL
5660
void SetSceneConfiguration(const SceneConfiguration& config) override;
5761
[[nodiscard]] const SceneConfiguration& GetSceneConfiguration() const override;
5862
void UpdateScene() override;
63+
void ReviseEntityPresence(AZ::EntityId entityId) override;
5964

6065
// AzFramework::EntityContextEventBus overrides
6166
void OnEntityContextCreateEntity(AZ::Entity& entity) override;
@@ -66,18 +71,28 @@ namespace RGL
6671
void OnLidarCreated() override;
6772
void OnLidarDestroyed() override;
6873

74+
// AZ::TickBus overrides
75+
void OnTick(float deltaTime, AZ::ScriptTimePoint time) override;
76+
6977
private:
78+
static bool HasVisuals(const AZ::Entity& entity);
79+
bool ShouldEntityBeExcluded(AZ::EntityId entityId) const;
7080
void ProcessEntity(const AZ::Entity& entity);
81+
void UpdateTagExcludedEntities();
7182

83+
SceneConfiguration m_sceneConfig;
7284
LidarSystem m_rglLidarSystem;
73-
7485
ModelLibrary m_modelLibrary;
86+
7587
AZStd::set<AZ::EntityId> m_excludedEntities;
7688
AZStd::set<AZ::EntityId> m_unprocessedEntities;
77-
SceneConfiguration m_sceneConfig;
89+
AZStd::vector<AZ::EntityId> m_managersToBeRemoved;
7890
AZStd::unordered_map<AZ::EntityId, AZStd::unique_ptr<EntityManager>> m_entityManagers;
79-
AZ::ScriptTimePoint m_sceneUpdateLastTime{};
91+
AZStd::vector<EntityTagListener> m_entityTagListeners;
8092

93+
AZStd::vector<LmbrCentral::Tag> m_excludedTags;
94+
95+
AZ::ScriptTimePoint m_sceneUpdateLastTime{};
8196
size_t m_activeLidarCount{};
8297
};
8398
} // namespace RGL

Code/Source/SceneConfiguration.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,19 @@ namespace RGL
6161
serializeContext->Class<SceneConfiguration>()
6262
->Version(0)
6363
->Field("TerrainIntensityConfig", &SceneConfiguration::m_terrainIntensityConfig)
64+
->Field("excludedTagNames", &SceneConfiguration::m_excludedTagNames)
6465
->Field("SkinnedMeshUpdate", &SceneConfiguration::m_isSkinnedMeshUpdateEnabled);
6566

6667
if (auto* editContext = serializeContext->GetEditContext())
6768
{
6869
editContext->Class<SceneConfiguration>("RGL Scene Configuration", "")
6970
->DataElement(
7071
AZ::Edit::UIHandlers::Default, &SceneConfiguration::m_terrainIntensityConfig, "Terrain Intensity Configuration", "")
72+
->DataElement(
73+
AZ::Edit::UIHandlers::Default,
74+
&SceneConfiguration::m_excludedTagNames,
75+
"Raycast excluded Tag names",
76+
"Entities tagged with names present in this list will not be included in raycasting.")
7177
->DataElement(
7278
AZ::Edit::UIHandlers::Default,
7379
&SceneConfiguration::m_isSkinnedMeshUpdateEnabled,

Code/rgl_files.cmake

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ set(FILES
1818
Source/Entity/MeshEntityManager.h
1919
Source/Entity/EntityManager.cpp
2020
Source/Entity/EntityManager.h
21+
Source/Entity/EntityTagListener.cpp
22+
Source/Entity/EntityTagListener.h
2123
Source/Entity/MaterialEntityManager.cpp
2224
Source/Entity/MaterialEntityManager.h
2325
Source/Entity/Terrain/TerrainData.cpp

0 commit comments

Comments
 (0)