PxU32 physx::NpRigidDynamicGetShapes(Scb::Body& body, void* const *&shapes)
{
    NpRigidDynamic* a = static_cast<NpRigidDynamic*>(body.getScBody().getPxActor());
    NpShapeManager& sm = a->getShapeManager();
    shapes = reinterpret_cast<void *const *>(sm.getShapes());
    return sm.getNbShapes();
}
NpRigidDynamic* NpRigidDynamic::createObject(PxU8*& address, PxDeserializationContext& context)
{
    NpRigidDynamic* obj = new (address) NpRigidDynamic(PxBaseFlag::eIS_RELEASABLE);
    address += sizeof(NpRigidDynamic);
    obj->importExtraData(context);
    obj->resolveReferences(context);
    return obj;
}
// PT: this is really the same as Sq::getGlobalPose() specialized for dynamic shapes
static PX_INLINE void getGlobalPose(PxTransform& transform, const NpShape& shape, const NpRigidDynamic& npRigidDynamic)
{
	// Same as:
//	transform = npRigidDynamic.getGlobalPoseFast() * shape.getLocalPose();

	// Same as:
//	transform = npRigidDynamic.getGlobalPoseFast() * npRigidDynamic.getCMassLocalPoseFast() * shape.getScbShape().getShape2Body();

	// Same as:
	transform = npRigidDynamic.getScbBodyFast().getBody2World() * shape.getScbShape().getShape2Body();
}
void SceneQueryManager::processSimUpdates()
{
	PX_PROFILE_ZONE("Sim.updatePruningTrees", mScene.getContextId());

	{
		PX_PROFILE_ZONE("SceneQuery.processActiveShapes", mScene.getContextId());

		// update all active objects
		BodyCore*const* activeBodies = mScene.getScScene().getActiveBodiesArray();
		PxU32 nbActiveBodies = mScene.getScScene().getNumActiveBodies();

#define NB_BATCHED_OBJECTS	128
		PrunerHandle batchedHandles[NB_BATCHED_OBJECTS];
		PxU32 nbBatchedObjects = 0;
		Pruner* pruner = mPrunerExt[PruningIndex::eDYNAMIC].pruner();

		while(nbActiveBodies--)
		{
			// PT: TODO: don't put frozen objects in "active bodies" array? After all they
			// are also not included in the 'active transforms' or 'active actors' arrays.
			BodyCore* currentBody = *activeBodies++;
			if(currentBody->isFrozen())
				continue;

			PxActorType::Enum type;
			PxRigidBody* pxBody = static_cast<PxRigidBody*>(getPxActorFromBodyCore(currentBody, type));
			PX_ASSERT(pxBody->getConcreteType()==PxConcreteType::eRIGID_DYNAMIC || pxBody->getConcreteType()==PxConcreteType::eARTICULATION_LINK);

			NpShapeManager* shapeManager;
			if(type==PxActorType::eRIGID_DYNAMIC)
			{
				NpRigidDynamic* rigidDynamic = static_cast<NpRigidDynamic*>(pxBody);
				shapeManager = &rigidDynamic->getShapeManager();
			}
			else
			{
				NpArticulationLink* articulationLink = static_cast<NpArticulationLink*>(pxBody);
				shapeManager = &articulationLink->getShapeManager();
			}

			const PxU32 nbShapes = shapeManager->getNbShapes();
			for(PxU32 i=0; i<nbShapes; i++)
			{
				const PrunerData data = shapeManager->getPrunerData(i);
				if(data!=SQ_INVALID_PRUNER_DATA)
				{
					// PT: index can't be zero here!
					PX_ASSERT(getPrunerIndex(data)==PruningIndex::eDYNAMIC);

					const PrunerHandle handle = getPrunerHandle(data);

					if(!mPrunerExt[PruningIndex::eDYNAMIC].isDirty(handle))	// PT: if dirty, will be updated in "flushShapes"
					{
						batchedHandles[nbBatchedObjects] = handle;

						PxBounds3* bounds;
						const PrunerPayload& pp = pruner->getPayload(handle, bounds);
						computeDynamicWorldAABB(*bounds, *(reinterpret_cast<Scb::Shape*>(pp.data[0])), *(reinterpret_cast<Scb::Actor*>(pp.data[1])));
						nbBatchedObjects++;

						if(nbBatchedObjects==NB_BATCHED_OBJECTS)
						{
							mPrunerExt[PruningIndex::eDYNAMIC].invalidateTimestamp();
							pruner->updateObjects(batchedHandles, NULL, nbBatchedObjects);
							nbBatchedObjects = 0;
						}
					}
				}
			}
		}
		if(nbBatchedObjects)
		{
			mPrunerExt[PruningIndex::eDYNAMIC].invalidateTimestamp();
			pruner->updateObjects(batchedHandles, NULL, nbBatchedObjects);
		}
	}

	// flush user modified objects
	flushShapes();

	for(PxU32 i=0;i<PruningIndex::eCOUNT;i++)
	{
		if(mPrunerExt[i].pruner() && mPrunerExt[i].type() == PxPruningStructureType::eDYNAMIC_AABB_TREE)
			static_cast<AABBPruner*>(mPrunerExt[i].pruner())->buildStep();

		mPrunerExt[i].pruner()->commit();
	}
}