Divide Framework 0.1
A free and open-source 3D Framework under heavy development
Loading...
Searching...
No Matches
PhysXSceneInterface.cpp
Go to the documentation of this file.
1
2
4#include "Headers/PhysX.h"
5
13
14#include <physx/PxSceneDesc.h>
15#include <physx/PxSceneLock.h>
16#include <physx/PxPhysics.h>
17
18#include <physx/extensions/PxDefaultCpuDispatcher.h>
19#include <physx/extensions/PxDefaultSimulationFilterShader.h>
20
21namespace Divide
22{
23 namespace
24 {
25 constexpr U32 g_parallelPartitionSize = 32;
26 }
27
29 {
31 };
32#ifdef USE_MBP
33
34 static void setupMBP( physx::PxScene& scene )
35 {
36 using namespace physx;
37
38 const float range = 1000.0f;
39 const PxU32 subdiv = 4;
40 // const PxU32 subdiv = 1;
41 // const PxU32 subdiv = 2;
42 // const PxU32 subdiv = 8;
43
44 const PxVec3 min( -range );
45 const PxVec3 max( range );
46 const PxBounds3 globalBounds( min, max );
47
48 PxBounds3 bounds[256];
49 const PxU32 nbRegions = PxBroadPhaseExt::createRegionsFromWorldBounds( bounds, globalBounds, subdiv );
50
51 for ( PxU32 i = 0; i < nbRegions; i++ )
52 {
53 PxBroadPhaseRegion region;
54 region.bounds = bounds[i];
55 region.userData = (void*)i;
56 scene.addBroadPhaseRegion( region );
57 }
58 }
59#endif //USE_MBP
60
62 : PhysicsSceneInterface( parentScene )
63 {
64 }
65
67 {
68 release();
69 }
70
72 {
73 const PhysX& physX = static_cast<PhysX&>(_parentScene.context().pfx().getImpl());
74 physx::PxPhysics* gPhysicsSDK = physX.getSDK();
75 // Create the scene
76 if ( !gPhysicsSDK )
77 {
78 Console::errorfn( LOCALE_STR( "ERROR_PHYSX_SDK" ) );
79 return false;
80 }
81
82 physx::PxSceneDesc sceneDesc( gPhysicsSDK->getTolerancesScale() );
83 sceneDesc.gravity = physx::PxVec3( DEFAULT_GRAVITY.x, DEFAULT_GRAVITY.y, DEFAULT_GRAVITY.z );
84 if ( !sceneDesc.cpuDispatcher )
85 {
86 _cpuDispatcher = physx::PxDefaultCpuDispatcherCreate( std::min(std::thread::hardware_concurrency(), 4u) );
87 if ( !_cpuDispatcher )
88 {
89 Console::errorfn( LOCALE_STR( "ERROR_PHYSX_INTERFACE_CPU_DISPATCH" ) );
90 }
91 sceneDesc.cpuDispatcher = _cpuDispatcher;
92 }
93
94 if ( !sceneDesc.filterShader )
95 {
96 sceneDesc.filterShader = physx::PxDefaultSimulationFilterShader;
97 }
98
99#if PX_SUPPORT_GPU_PHYSX
100 if ( !sceneDesc.cudaContextManager )
101 sceneDesc.cudaContextManager = physX.cudaContextManager();
102#endif //PX_SUPPORT_GPU_PHYSX
103
104 //sceneDesc.frictionType = physx::PxFrictionType::eTWO_DIRECTIONAL;
105 //sceneDesc.frictionType = physx::PxFrictionType::eONE_DIRECTIONAL;
106 //sceneDesc.flags |= physx::PxSceneFlag::eENABLE_GPU_DYNAMICS;
107 sceneDesc.flags |= physx::PxSceneFlag::eENABLE_PCM;
108 //sceneDesc.flags |= physx::PxSceneFlag::eENABLE_AVERAGE_POINT;
109 sceneDesc.flags |= physx::PxSceneFlag::eENABLE_STABILIZATION;
110 //sceneDesc.flags |= physx::PxSceneFlag::eADAPTIVE_FORCE;
111 sceneDesc.flags |= physx::PxSceneFlag::eENABLE_ACTIVE_ACTORS;
112 sceneDesc.sceneQueryUpdateMode = physx::PxSceneQueryUpdateMode::eBUILD_ENABLED_COMMIT_DISABLED;
113
114 //sceneDesc.flags |= physx::PxSceneFlag::eDISABLE_CONTACT_CACHE;
115 //sceneDesc.broadPhaseType = physx::PxBroadPhaseType::eGPU;
116 //sceneDesc.broadPhaseType = physx::PxBroadPhaseType::eSAP;
117 sceneDesc.gpuMaxNumPartitions = 8;
118 //sceneDesc.solverType = physx::PxSolverType::eTGS;
119#ifdef USE_MBP
120 sceneDesc.broadPhaseType = physx::PxBroadPhaseType::eMBP;
121#endif //USE_MBP
122
123 _gScene = gPhysicsSDK->createScene( sceneDesc );
124 if ( !_gScene )
125 {
126 Console::errorfn( LOCALE_STR( "ERROR_PHYSX_INTERFACE_CREATE_SCENE" ) );
127 return false;
128 }
129
130 physx::PxSceneWriteLock scopedLock( *_gScene );
131 [[maybe_unused]] const physx::PxSceneFlags flag = _gScene->getFlags();
132 //_gScene->setVisualizationParameter(physx::PxVisualizationParameter::eSCALE, 1.0);
133 //_gScene->setVisualizationParameter(physx::PxVisualizationParameter::eCOLLISION_SHAPES, 1.0f);
134
135 if constexpr( !Config::Build::IS_SHIPPING_BUILD )
136 {
137 physx::PxPvdSceneClient* pvdClient = _gScene->getScenePvdClient();
138 if ( pvdClient != nullptr )
139 {
140 pvdClient->setScenePvdFlag( physx::PxPvdSceneFlag::eTRANSMIT_CONSTRAINTS, true );
141 pvdClient->setScenePvdFlag( physx::PxPvdSceneFlag::eTRANSMIT_CONTACTS, true );
142 pvdClient->setScenePvdFlag( physx::PxPvdSceneFlag::eTRANSMIT_SCENEQUERIES, true );
143 }
144 }
145#ifdef USE_MBP
146 setupMBP( *_gScene );
147#endif //USE_MBP
148
149 return true;
150 }
151
152 bool PhysXSceneInterface::isInit() const noexcept
153 {
154 return _gScene != nullptr;
155 }
156
157#define SAFE_RELEASE(X) if (X != nullptr) { X->release(); X = nullptr;}
159 {
160 Console::d_printfn( LOCALE_STR( "STOP_PHYSX_SCENE_INTERFACE" ) );
161
162 idle();
163
166 }
167
169 {
170 if ( _gScene == nullptr )
171 {
172 return;
173 }
174
176
177 bool expected = true;
178 if ( _rigidActorsQueued.compare_exchange_strong( expected, false ) )
179 {
180 PROFILE_SCOPE( "Registering rigid actors", Profiler::Category::Physics );
181
182 PhysXActor* crtActor = nullptr;
183 while ( _sceneRigidQueue.try_dequeue( crtActor ) )
184 {
185 _sceneRigidActors.push_back( crtActor );
186 _gScene->addActor( *(crtActor->_actor) );
187 }
188 }
189 else
190 {
191 const U32 componentMask = _parentScene.context().componentMask();
192
195 _parentScene.context().componentMask( componentMask );
196 }
197 }
198
199 void PhysXSceneInterface::frameEnded( [[maybe_unused]] const U64 deltaTimeGameUS )
200 {
201 if ( _gScene == nullptr )
202 {
203 return;
204 }
206
207 bool expected = true;
208 if ( _physxResultsPending.compare_exchange_strong( expected, false ) )
209 {
210 PROFILE_SCOPE( "Waiting for simulation results", Profiler::Category::Physics );
211
212 bool block = false;
213 while ( !_gScene->fetchResults( block ) )
214 {
215 idle();
216 block = true;
217 }
218 }
219
220 // retrieve array of actors that moved
221 physx::PxU32 nbActiveActors = 0;
222 physx::PxActor** activeActors = _gScene->getActiveActors( nbActiveActors );
223
224 if ( nbActiveActors > 0u )
225 {
226 PROFILE_SCOPE( "Updating actors", Profiler::Category::Physics );
227
228 // update each render object with the new transform
229 ParallelForDescriptor descriptor = {};
230 descriptor._iterCount = to_U32( nbActiveActors );
231 descriptor._partitionSize = g_parallelPartitionSize;
232 Parallel_For( parentScene().context().taskPool( TaskPoolType::HIGH_PRIORITY ), descriptor, [activeActors]( const Task*, const U32 start, const U32 end )
233 {
234 for ( U32 i = start; i < end; ++i )
235 {
236 UpdateActor( activeActors[i] );
237 }
238 });
239 }
240 }
241
242 void PhysXSceneInterface::UpdateActor( physx::PxActor* actor )
243 {
245
246 const physx::PxRigidActor* rigidActor = static_cast<physx::PxRigidActor*>(actor);
247 TransformComponent* tComp = static_cast<SceneGraphNode*>(rigidActor->userData)->get<TransformComponent>();
248
249 const physx::PxTransform pT = rigidActor->getGlobalPose();
250 const physx::PxQuat pQ = pT.q.getConjugate();
251 tComp->setRotation( Quaternion<F32>( pQ.x, pQ.y, pQ.z, pQ.w ) );
252 tComp->setPosition( pT.p.x, pT.p.y, pT.p.z );
253 }
254
255 void PhysXSceneInterface::frameStarted( const U64 deltaTimeGameUS )
256 {
258
259 if ( _gScene != nullptr )
260 {
261 _gScene->simulate( Time::MicrosecondsToMilliseconds<physx::PxReal>( deltaTimeGameUS ) );
262 _physxResultsPending.store(true);
263 }
264 }
265
267 {
268 assert( actor != nullptr );
269 // We DO NOT take ownership of actors. Ownership remains with RigidBodyComponent
270 _sceneRigidQueue.enqueue( actor );
271 _rigidActorsQueued.store( true );
272 }
273
274 void PhysXSceneInterface::updateRigidActor( physx::PxRigidActor* oldActor, physx::PxRigidActor* newActor ) const
275 {
276 if ( oldActor != nullptr )
277 {
278 _gScene->removeActor( *oldActor );
279 }
280 if ( newActor != nullptr )
281 {
282 _gScene->addActor( *newActor );
283 }
284 }
285
286 bool PhysXSceneInterface::intersect( const Ray& intersectionRay, const vec2<F32> range, vector<SGNRayResult>& intersectionsOut ) const
287 {
288 physx::PxRaycastBuffer hit;
289
290 const physx::PxHitFlags outputFlags = physx::PxHitFlag::eMESH_ANY | physx::PxHitFlag::ePOSITION | physx::PxHitFlag::eNORMAL;
291 const physx::PxVec3 unitDir = Util::toVec3( intersectionRay._direction );
292 const physx::PxVec3 origin = Util::toVec3( intersectionRay._origin );
293
295
296 if ( _gScene->raycast( origin + unitDir * range.min, unitDir, range.max, hit, outputFlags ) )
297 {
298 const physx::PxU32 numHits = hit.getNbAnyHits();
299
300 for ( physx::PxU32 i = 0; i < numHits; ++i )
301 {
302 hit.block = hit.getAnyHit( i );
303 PX_ASSERT( hit.block.shape );
304 PX_ASSERT( hit.block.actor );
305 PX_ASSERT( hit.block.distance <= probeLength + extra );
306
307 const SceneGraphNode* node = static_cast<SceneGraphNode*>(hit.block.actor->userData);
308 intersectionsOut.push_back( {
309 node->getGUID(),
310 hit.block.distance,
311 false,
312 node->name().c_str()
313 } );
314 }
315 return numHits > 0;
316 }
317
318 return false;
319 }
320} //namespace Divide
#define LOCALE_STR(X)
Definition: Localization.h:91
#define SAFE_RELEASE(X)
Definition: PhysX.cpp:211
#define PROFILE_SCOPE_AUTO(CATEGORY)
Definition: Profiler.h:87
#define PROFILE_SCOPE(NAME, CATEGORY)
Definition: Profiler.h:86
FORCE_INLINE I64 getGUID() const noexcept
Definition: GUIDWrapper.h:51
PhysicsAPIWrapper & getImpl()
Definition: PXDevice.h:68
physx::PxRigidActor * _actor
Definition: PhysXActor.h:99
physx::PxPhysics * getSDK() const noexcept
Definition: PhysX.h:91
physx::PxDefaultCpuDispatcher * _cpuDispatcher
void frameStarted(U64 deltaTimeGameUS) override
Custom process step.
void frameEnded(U64 deltaTimeGameUS) override
Physics update callback for custom behavior.
void idle() override
Custom physics idle calls.
bool init() override
Pre PHYSICS_DEVICE initialisation call.
virtual ~PhysXSceneInterface() override
void updateRigidActor(physx::PxRigidActor *oldActor, physx::PxRigidActor *newActor) const
bool intersect(const Ray &intersectionRay, vec2< F32 > range, vector< SGNRayResult > &intersectionsOut) const
static void UpdateActor(physx::PxActor *actor)
PhysXSceneInterface(Scene &parentScene)
void addRigidActor(PhysXActor *actor)
std::atomic_bool _physxResultsPending
bool isInit() const noexcept override
Should return true if init() was called successfully.
void release() override
Called on interface destruction.
PlatformContext & context() noexcept
PXDevice & pfx() noexcept
void idle(bool fast=true, U64 deltaTimeUSGame=0u, U64 deltaTimeUSApp=0u)
Scene & parentScene() noexcept
void setPosition(const vec3< F32 > &position) override
Component <-> Transform interface.
void setRotation(const vec3< F32 > &axis, Angle::DEGREES< F32 > degrees) override
constexpr bool IS_SHIPPING_BUILD
Definition: config.h:60
constexpr Optick::Category::Type Physics
Definition: Profiler.h:62
vec3< F32 > toVec3(const physx::PxVec3 &vec) noexcept
Definition: PhysXActor.cpp:10
Handle console commands that start with a forward slash.
Definition: AIProcessor.cpp:7
constexpr U32 to_U32(const T value)
uint8_t U8
eastl::vector< Type > vector
Definition: Vector.h:42
static const vec3< F32 > DEFAULT_GRAVITY
Definition: MathVectors.h:1445
void Parallel_For(TaskPool &pool, const ParallelForDescriptor &descriptor, const DELEGATE< void, const Task *, U32, U32 > &cbk)
Definition: TaskPool.cpp:428
uint32_t U32
uint64_t U64
constexpr auto to_base(const Type value) -> Type
Definition: PhysX.h:45
static NO_INLINE void d_printfn(const char *format, T &&... args)
static NO_INLINE void errorfn(const char *format, T &&... args)
U32 _partitionSize
How many elements should we process per async task.
Definition: TaskPool.h:45
U32 _iterCount
For loop iteration count.
Definition: TaskPool.h:43
vec3< F32 > _origin
Definition: Ray.h:60
vec3< F32 > _direction
Definition: Ray.h:61