AGX Dynamics 2.42.3.0
Loading...
Searching...
No Matches
EnvironmentInternalData.h
Go to the documentation of this file.
1/*
2Copyright 2007-2025. Algoryx Simulation AB.
3
4All AGX source code, intellectual property, documentation, sample code,
5tutorials, scene files and technical white papers, are copyrighted, proprietary
6and confidential material of Algoryx Simulation AB. You may not download, read,
7store, distribute, publish, copy or otherwise disseminate, use or expose this
8material unless having a written signed agreement with Algoryx Simulation AB, or having been
9advised so by Algoryx Simulation AB for a time limited evaluation, or having purchased a
10valid commercial license from Algoryx Simulation AB.
11
12Algoryx Simulation AB disclaims all responsibilities for loss or damage caused
13from using this software, unless otherwise stated in written agreements with
14Algoryx Simulation AB.
15*/
16
17#pragma once
18
22
23#include <agxVehicle/Track.h>
24
25#include <agx/RigidBody.h>
26#include <agx/InternalData.h>
27#include <agx/BitState.h>
28
29namespace agxSensor
30{
32
33 class Environment;
34 static constexpr agx::InternalData::Source SENSOR_DATA_SOURCE = agx::InternalData::SENSOR_ENVIRONMENT;
35
36 struct AGXSENSOR_EXPORT RtInternalData : RtInstanceData
37 {
38 struct State
39 {
40 enum Flag : agx::UInt32
41 {
42 ENTITY_ID_OWNER = 1 << 0,
44 MATERIAL_OWNER = 1 << 1,
45 };
46
47 agx::BitState<Flag, agx::UInt32> flags;
48 };
49
50 using RtInstanceData::RtInstanceData;
51
52 virtual ~RtInternalData()
53 {
54 if ( getEntityId() != NullRtEntityId && state.flags.Is( State::ENTITY_ID_OWNER ) ) {
55 destroyEntityId();
56 state.flags.update( State::ENTITY_ID_OWNER, false );
57 }
58 }
59
60 State state;
61 };
62 using RtInternalDataRef = agx::ref_ptr<RtInternalData>;
63
64 struct EnvInternalData : agx::Referenced
65 {
66 RtInternalDataRef rtData;
67
68 Environment* environment = nullptr;
69 };
70
71 template<typename T>
72 inline const EnvInternalData* getEnvData( const T& instance )
73 {
74 return agx::InternalData::get<EnvInternalData>( instance,
75 SENSOR_DATA_SOURCE );
76 }
77
78 template<typename T>
79 inline EnvInternalData* getEnvData( T&& instance )
80 {
81 return const_cast<EnvInternalData*>( getEnvData( (const T&)instance ) );
82 }
83
84 template<typename T>
85 inline EnvInternalData* getOrCreateEnvData( T&& instance )
86 {
87 return agx::InternalData::getOrCreate<EnvInternalData>( instance,
88 SENSOR_DATA_SOURCE );
89 }
90
91 template<typename T>
92 inline const RtInternalData* getRtData( const T& instance )
93 {
94 const auto envData = getEnvData( instance );
95 return envData != nullptr ?
96 envData->rtData :
97 nullptr;
98 }
99
100 template<typename T>
101 inline RtInternalData* getOrCreateRtData( T&& instance )
102 {
103 if ( instance == nullptr )
104 return nullptr;
105
106 // Important that it's a reference to the pointer when
107 // it's assigned in the return statement.
108 auto& rtData = getOrCreateEnvData( instance )->rtData;
109 return rtData != nullptr ?
110 rtData.get() :
111 ( rtData = new RtInternalData() ).get();
112 }
113
114 template<typename T>
115 bool isRtMaterialOwner( const T& instance )
116 {
117 const RtInternalData* rtData = getRtData( instance );
118 return rtData != nullptr &&
119 rtData->state.flags.Is( RtInternalData::State::MATERIAL_OWNER );
120 }
121
122 template<typename T>
123 void updateRtMaterial( T&& instance, RtMaterialInstance material )
124 {
125 if ( instance == nullptr )
126 return;
127
128 RtInternalData* rtData = getOrCreateRtData( instance );
129 rtData->setMaterial( material );
130 }
131
132 AGXSENSOR_EXPORT void updateRtMaterial( agxVehicle::Track* track , RtMaterialInstance material );
133
134 inline void updateRtMaterial( RtInternalData* rtData,
135 RtMaterialInstance material,
136 bool overrideInherited )
137 {
138 // Use if override or if not owner of a material.
139 const auto useGivenHandle = overrideInherited ||
140 !rtData->state.flags.Is( RtInternalData::State::MATERIAL_OWNER );
141 if ( useGivenHandle ) {
142 rtData->setMaterial( material );
143 rtData->state.flags.update( RtInternalData::State::MATERIAL_OWNER, overrideInherited );
144 }
145 }
146
147 inline void updateRtMaterial( agxCollide::Shape* shape,
148 RtMaterialInstance material,
149 bool overrideInherited )
150 {
151 if ( shape == nullptr )
152 return;
153
154 updateRtMaterial( getOrCreateRtData( shape ),
155 material,
156 overrideInherited );
157 }
158
159 inline void updateRtMaterial( agxCollide::Geometry* geometry,
160 RtMaterialInstance material,
161 bool overrideInherited )
162 {
163 if ( geometry == nullptr )
164 return;
165
166 updateRtMaterial( getOrCreateRtData( geometry ),
167 material,
168 overrideInherited );
169
170 for ( const auto& shape : geometry->getShapes() )
171 updateRtMaterial( shape, material, false );
172 }
173
174 inline void updateRtMaterial( agx::RigidBody* rb,
175 RtMaterialInstance material,
176 bool overrideInherited )
177 {
178 if ( rb == nullptr )
179 return;
180
181 updateRtMaterial( getOrCreateRtData( rb ),
182 material,
183 overrideInherited );
184
185 for ( const auto& geometry : rb->getGeometries() ) {
186 // Only do this if the geometry has an inherited material because
187 // we don't want to assign new material to shapes of an owning
188 // parent geometry. E.g.,
189 // updateRtSurfaceMaterialHandle( rb->getGeometries()[47], ... );
190 // updateRtSurfaceMaterialHandle( rb, ... );
191 // it's unexpected the shapes of geometry index 47 has different
192 // material from their parent geometry.
193 if ( !isRtMaterialOwner( geometry ) )
194 updateRtMaterial( geometry, material, false );
195 }
196 }
197
198 template<typename T>
199 inline RtMaterialInstance getRtMaterial( const T& instance )
200 {
201 if ( instance == nullptr )
202 return {};
203
204 const RtInternalData* rtData = getRtData( instance );
205 return rtData != nullptr ?
206 rtData->getMaterial() :
207 RtMaterialInstance{};
208 }
209
210 template<typename T>
211 RtEntityId getOrCreateRtEntityIdImpl( T&& instance,
213 bool overrideInherited = false )
214 {
215 if ( instance == nullptr )
216 return NullRtEntityId;
217
218 RtInternalData* rtData = getOrCreateRtData( instance );
219
220 // Preventing 'create' when this instance already has its own id.
221 overrideInherited = overrideInherited &&
222 !rtData->state.flags.Is( RtInternalData::State::ENTITY_ID_OWNER );
223
224 // If, e.g., a geometry got overridden, its non-owning shapes should
225 // receive the new geometry id 'hint'.
226 // NOTE: Is this a bad (unexpected) side effect, remove it and make
227 // it explicit as an argument for the caller do deside.
228 const auto updateNonOwningId = !overrideInherited &&
229 hint != NullRtEntityId &&
230 hint != rtData->getEntityId() &&
231 !rtData->state.flags.Is( RtInternalData::State::ENTITY_ID_OWNER );
232
233 if ( rtData->getEntityId() == NullRtEntityId || overrideInherited || updateNonOwningId ) {
234 // Assuming 'hint' not null is because there's a single other owner
235 // of this id. E.g., rigid body:
236 // auto rbId = getOrCreateRtEntityId( rb ); <- hint == null == owner
237 // for ( auto& geometry : rb->getGeometries() )
238 // getorCreateRtEntityId( geometry, rbId ); <- hint != null == NOT owner
239 const auto isOwner = hint == NullRtEntityId || overrideInherited;
240 rtData->state.flags.update( RtInternalData::State::ENTITY_ID_OWNER,
241 isOwner );
242
243 rtData->setEntityId( isOwner ?
245 hint );
246 }
247
248 return rtData->getEntityId();
249 }
250
251 template<typename T>
252 RtEntityId getOrCreateRtEntityId( T&& instance,
254 bool overrideInherited = false )
255 {
256 if ( instance == nullptr )
257 return NullRtEntityId;
258 else if ( auto track = instance->template asSafe<agxVehicle::Track>() )
259 return getOrCreateRtEntityId( track, hint, overrideInherited );
260
261 return getOrCreateRtEntityIdImpl( instance, hint, overrideInherited );
262 }
263
264 AGXSENSOR_EXPORT RtEntityId getOrCreateRtEntityId( agxVehicle::Track* track,
266 bool overrideInherited = false );
267
268 template<typename T>
269 RtEntityId getRtEntityId( const T& instance )
270 {
271 const RtInternalData* rtData = getRtData( instance );
272 return rtData != nullptr ?
273 rtData->getEntityId() :
275 }
276
277 template<typename T>
278 bool isRtEntityIdOwner( const T& instance )
279 {
280 const RtInternalData* rtData = getRtData( instance );
281 return rtData != nullptr &&
282 rtData->state.flags.Is( RtInternalData::State::ENTITY_ID_OWNER );
283 }
284
285 template<typename T>
286 bool shouldOverrideRtEntityId( const T& instance,
287 RtEntityId currentId,
288 bool overrideInherited )
289 {
290 // Override inherited if desired...:
291 return overrideInherited &&
292 // ...and instance already has an id...
293 currentId != NullRtEntityId &&
294 // ...that is inherited (not owner).
295 !isRtEntityIdOwner( &instance );
296 }
297
302 inline RtEntityId manageRtEntityId( agxCollide::Shape* shape,
303 bool overrideInherited = true )
304 {
305 return getOrCreateRtEntityId( shape,
307 overrideInherited );
308 }
309
315 inline RtEntityId manageRtEntityId( agxCollide::Geometry* geometry,
316 bool overrideInherited = true )
317 {
318 if ( geometry == nullptr )
319 return NullRtEntityId;
320
321 auto geometryId = getRtEntityId( geometry );
322
323 const auto doOverride = shouldOverrideRtEntityId( *geometry,
324 geometryId,
325 overrideInherited );
326 if ( geometryId == NullRtEntityId || doOverride ) {
327 geometryId = getOrCreateRtEntityId( geometry,
328 geometryId,
329 doOverride );
330
331 // Propagating id of the geometry to the shapes if the shape
332 // doesn't already have its own.
333 for ( const auto& shape : geometry->getShapes() )
334 getOrCreateRtEntityId( shape,
335 geometryId,
336 false );
337 }
338
339 return geometryId;
340 }
341
347 inline RtEntityId manageRtEntityId( agx::RigidBody* rb,
348 bool overrideInherited = true )
349 {
350 if ( rb == nullptr )
351 return NullRtEntityId;
352
353 auto rbId = getRtEntityId( rb );
354
355 const auto doOverride = shouldOverrideRtEntityId( *rb,
356 rbId,
357 overrideInherited );
358 if ( rbId == NullRtEntityId || doOverride ) {
359 rbId = getOrCreateRtEntityId( rb,
360 rbId,
361 doOverride );
362
363 // Propagating id if the rigid body to all its geometries and shapes.
364 for ( const auto& geometry : rb->getGeometries() ) {
365 getOrCreateRtEntityId( geometry,
366 rbId,
367 false );
368
369 // Stop the propagation to shapes if this geometry is
370 // id-owner since the shapes of it may be non-owners and
371 // it's expected they have the id of the geometry.
372 if ( isRtEntityIdOwner( geometry ) )
373 continue;
374
375 for ( const auto& shape : geometry->getShapes() )
376 getOrCreateRtEntityId( shape,
377 rbId,
378 false );
379 }
380 }
381
382 return rbId;
383 }
384
386}
#define AGXSENSOR_EXPORT
The geometry representation used by the collision detection engine.
Definition: Geometry.h:92
const ShapeRefVector & getShapes() const
Base class for a shape.
Definition: Shape.h:58
static RtEntityId createId()
Creates a new entity ID to use for mapping.
Assembly object representing a continuous track with a given number of shoes (nodes).
Base class providing referencing counted objects.
Definition: Referenced.h:120
The rigid body class, combining a geometric model and a frame of reference.
Definition: RigidBody.h:49
const agxCollide::GeometryRefVector & getGeometries() const
Smart pointer for handling referenced counted objects.
Definition: ref_ptr.h:30
#define DOXYGEN_END_INTERNAL_BLOCK()
Definition: macros.h:89
#define DOXYGEN_START_INTERNAL_BLOCK()
Definition: macros.h:88
The agxSensor namespace contains components to model real-time sensors connected to the physics of AG...
constexpr RtEntityId NullRtEntityId
Null entity id.
RtEntityId
Entity id > 0 to access user data given raytrace results including ENTITY_ID_I32.
The agx namespace contains the dynamics/math part of the AGX Dynamics API.
uint32_t UInt32
Definition: Integer.h:32