Revision control
++ // Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
++ // Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
++ // SPDX-FileCopyrightText: Copyright (c) 2008-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
++ // SPDX-License-Identifier: Apache-2.0
++
++ // suppress LNK4221
++ #include "foundation/PxPreprocessor.h"
++ PX_DUMMY_SYMBOL
++
++ #if PX_SUPPORT_PVD
++
++ #include "foundation/PxSimpleTypes.h"
++
++ #include "PxMetaDataObjects.h"
++ #include "PxPvdDataStream.h"
++ #include "PxScene.h"
++ #include "ScBodyCore.h"
++ #include "PvdMetaDataExtensions.h"
++ #include "PvdMetaDataPropertyVisitor.h"
++ #include "PvdMetaDataDefineProperties.h"
++ #include "PvdMetaDataBindingData.h"
++ #include "PxRigidDynamic.h"
++ #include "PxArticulationReducedCoordinate.h"
++ #include "PxArticulationLink.h"
++ #include "NpScene.h"
++ #include "NpPhysics.h"
++
++ #include "PvdTypeNames.h"
++ #include "PvdMetaDataPvdBinding.h"
++
++ using namespace physx;
++ using namespace Sc;
++ using namespace Vd;
++ using namespace Sq;
++
++ namespace physx
++ {
++ namespace Vd
++ {
++
++ struct NameValuePair
++ {
++ const char* mName;
++ PxU32 mValue;
++ };
++
++ #if PX_LINUX && PX_CLANG
++ #pragma clang diagnostic push
++ #pragma clang diagnostic ignored "-Wreserved-identifier"
++ #endif
++
++ static const NameValuePair g_physx_Sq_SceneQueryID__EnumConversion[] = {
++ { "QUERY_RAYCAST_ANY_OBJECT", PxU32(QueryID::QUERY_RAYCAST_ANY_OBJECT) },
++ { "QUERY_RAYCAST_CLOSEST_OBJECT", PxU32(QueryID::QUERY_RAYCAST_CLOSEST_OBJECT) },
++ { "QUERY_RAYCAST_ALL_OBJECTS", PxU32(QueryID::QUERY_RAYCAST_ALL_OBJECTS) },
++ { "QUERY_OVERLAP_SPHERE_ALL_OBJECTS", PxU32(QueryID::QUERY_OVERLAP_SPHERE_ALL_OBJECTS) },
++ { "QUERY_OVERLAP_AABB_ALL_OBJECTS", PxU32(QueryID::QUERY_OVERLAP_AABB_ALL_OBJECTS) },
++ { "QUERY_OVERLAP_OBB_ALL_OBJECTS", PxU32(QueryID::QUERY_OVERLAP_OBB_ALL_OBJECTS) },
++ { "QUERY_OVERLAP_CAPSULE_ALL_OBJECTS", PxU32(QueryID::QUERY_OVERLAP_CAPSULE_ALL_OBJECTS) },
++ { "QUERY_OVERLAP_CONVEX_ALL_OBJECTS", PxU32(QueryID::QUERY_OVERLAP_CONVEX_ALL_OBJECTS) },
++ { "QUERY_LINEAR_OBB_SWEEP_CLOSEST_OBJECT", PxU32(QueryID::QUERY_LINEAR_OBB_SWEEP_CLOSEST_OBJECT) },
++ { "QUERY_LINEAR_CAPSULE_SWEEP_CLOSEST_OBJECT", PxU32(QueryID::QUERY_LINEAR_CAPSULE_SWEEP_CLOSEST_OBJECT) },
++ { "QUERY_LINEAR_CONVEX_SWEEP_CLOSEST_OBJECT", PxU32(QueryID::QUERY_LINEAR_CONVEX_SWEEP_CLOSEST_OBJECT) },
++ { NULL, 0 }
++ };
++
++ #if PX_LINUX && PX_CLANG
++ #pragma clang diagnostic pop
++ #endif
++
++ struct SceneQueryIDConvertor
++ {
++ const NameValuePair* NameConversion;
++ SceneQueryIDConvertor() : NameConversion(g_physx_Sq_SceneQueryID__EnumConversion)
++ {
++ }
++ };
++
++ PvdMetaDataBinding::PvdMetaDataBinding() : mBindingData(PX_NEW(PvdMetaDataBindingData)())
++ {
++ }
++
++ PvdMetaDataBinding::~PvdMetaDataBinding()
++ {
++ for(OwnerActorsMap::Iterator iter = mBindingData->mOwnerActorsMap.getIterator(); !iter.done(); iter++)
++ {
++ iter->second->~OwnerActorsValueType();
++ PX_FREE(iter->second);
++ }
++
++ PX_DELETE(mBindingData);
++ }
++
++ template <typename TDataType, typename TValueType, typename TClassType>
++ static inline void definePropertyStruct(PvdDataStream& inStream, const char* pushName = NULL)
++ {
++ PvdPropertyDefinitionHelper& helper(inStream.getPropertyDefinitionHelper());
++ PvdClassInfoValueStructDefine definitionObj(helper);
++ bool doPush = pushName && *pushName;
++ if(doPush)
++ definitionObj.pushName(pushName);
++ visitAllPvdProperties<TDataType>(definitionObj);
++ if(doPush)
++ definitionObj.popName();
++ helper.addPropertyMessage(getPvdNamespacedNameForType<TClassType>(), getPvdNamespacedNameForType<TValueType>(), sizeof(TValueType));
++ }
++
++ template <typename TDataType>
++ static inline void createClassAndDefineProperties(PvdDataStream& inStream)
++ {
++ inStream.createClass<TDataType>();
++ PvdPropertyDefinitionHelper& helper(inStream.getPropertyDefinitionHelper());
++ PvdClassInfoDefine definitionObj(helper, getPvdNamespacedNameForType<TDataType>());
++ visitAllPvdProperties<TDataType>(definitionObj);
++ }
++
++ template <typename TDataType, typename TParentType>
++ static inline void createClassDeriveAndDefineProperties(PvdDataStream& inStream)
++ {
++ inStream.createClass<TDataType>();
++ inStream.deriveClass<TParentType, TDataType>();
++ PvdPropertyDefinitionHelper& helper(inStream.getPropertyDefinitionHelper());
++ PvdClassInfoDefine definitionObj(helper, getPvdNamespacedNameForType<TDataType>());
++ visitInstancePvdProperties<TDataType>(definitionObj);
++ }
++
++ template <typename TDataType, typename TConvertSrc, typename TConvertData>
++ static inline void defineProperty(PvdDataStream& inStream, const char* inPropertyName, const char* semantic)
++ {
++ PvdPropertyDefinitionHelper& helper(inStream.getPropertyDefinitionHelper());
++ // PxEnumTraits< TValueType > filterFlagsEnum;
++ TConvertSrc filterFlagsEnum;
++ const TConvertData* convertor = filterFlagsEnum.NameConversion;
++
++ for(; convertor->mName != NULL; ++convertor)
++ helper.addNamedValue(convertor->mName, convertor->mValue);
++
++ inStream.createProperty<TDataType, PxU32>(inPropertyName, semantic, PropertyType::Scalar, helper.getNamedValues());
++ helper.clearNamedValues();
++ }
++
++ template <typename TDataType, typename TConvertSrc, typename TConvertData>
++ static inline void definePropertyFlags(PvdDataStream& inStream, const char* inPropertyName)
++ {
++ defineProperty<TDataType, TConvertSrc, TConvertData>(inStream, inPropertyName, "Bitflag");
++ }
++ template <typename TDataType, typename TConvertSrc, typename TConvertData>
++ static inline void definePropertyEnums(PvdDataStream& inStream, const char* inPropertyName)
++ {
++ defineProperty<TDataType, TConvertSrc, TConvertData>(inStream, inPropertyName, "Enumeration Value");
++ }
++
++ static PX_FORCE_INLINE void registerPvdRaycast(PvdDataStream& inStream)
++ {
++ inStream.createClass<PvdRaycast>();
++ definePropertyEnums<PvdRaycast, SceneQueryIDConvertor, NameValuePair>(inStream, "type");
++ inStream.createProperty<PvdRaycast, PxFilterData>("filterData");
++ definePropertyFlags<PvdRaycast, PxEnumTraits<physx::PxQueryFlag::Enum>, PxU32ToName>(inStream, "filterFlags");
++ inStream.createProperty<PvdRaycast, PxVec3>("origin");
++ inStream.createProperty<PvdRaycast, PxVec3>("unitDir");
++ inStream.createProperty<PvdRaycast, PxF32>("distance");
++ inStream.createProperty<PvdRaycast, String>("hits_arrayName");
++ inStream.createProperty<PvdRaycast, PxU32>("hits_baseIndex");
++ inStream.createProperty<PvdRaycast, PxU32>("hits_count");
++ }
++
++ static PX_FORCE_INLINE void registerPvdSweep(PvdDataStream& inStream)
++ {
++ inStream.createClass<PvdSweep>();
++ definePropertyEnums<PvdSweep, SceneQueryIDConvertor, NameValuePair>(inStream, "type");
++ definePropertyFlags<PvdSweep, PxEnumTraits<physx::PxQueryFlag::Enum>, PxU32ToName>(inStream, "filterFlags");
++ inStream.createProperty<PvdSweep, PxVec3>("unitDir");
++ inStream.createProperty<PvdSweep, PxF32>("distance");
++ inStream.createProperty<PvdSweep, String>("geom_arrayName");
++ inStream.createProperty<PvdSweep, PxU32>("geom_baseIndex");
++ inStream.createProperty<PvdSweep, PxU32>("geom_count");
++ inStream.createProperty<PvdSweep, String>("pose_arrayName");
++ inStream.createProperty<PvdSweep, PxU32>("pose_baseIndex");
++ inStream.createProperty<PvdSweep, PxU32>("pose_count");
++ inStream.createProperty<PvdSweep, String>("filterData_arrayName");
++ inStream.createProperty<PvdSweep, PxU32>("filterData_baseIndex");
++ inStream.createProperty<PvdSweep, PxU32>("filterData_count");
++ inStream.createProperty<PvdSweep, String>("hits_arrayName");
++ inStream.createProperty<PvdSweep, PxU32>("hits_baseIndex");
++ inStream.createProperty<PvdSweep, PxU32>("hits_count");
++ }
++
++ static PX_FORCE_INLINE void registerPvdOverlap(PvdDataStream& inStream)
++ {
++ inStream.createClass<PvdOverlap>();
++ definePropertyEnums<PvdOverlap, SceneQueryIDConvertor, NameValuePair>(inStream, "type");
++ inStream.createProperty<PvdOverlap, PxFilterData>("filterData");
++ definePropertyFlags<PvdOverlap, PxEnumTraits<physx::PxQueryFlag::Enum>, PxU32ToName>(inStream, "filterFlags");
++ inStream.createProperty<PvdOverlap, PxTransform>("pose");
++ inStream.createProperty<PvdOverlap, String>("geom_arrayName");
++ inStream.createProperty<PvdOverlap, PxU32>("geom_baseIndex");
++ inStream.createProperty<PvdOverlap, PxU32>("geom_count");
++ inStream.createProperty<PvdOverlap, String>("hits_arrayName");
++ inStream.createProperty<PvdOverlap, PxU32>("hits_baseIndex");
++ inStream.createProperty<PvdOverlap, PxU32>("hits_count");
++ }
++
++ static PX_FORCE_INLINE void registerPvdSqHit(PvdDataStream& inStream)
++ {
++ inStream.createClass<PvdSqHit>();
++ inStream.createProperty<PvdSqHit, ObjectRef>("Shape");
++ inStream.createProperty<PvdSqHit, ObjectRef>("Actor");
++ inStream.createProperty<PvdSqHit, PxU32>("FaceIndex");
++ definePropertyFlags<PvdSqHit, PxEnumTraits<physx::PxHitFlag::Enum>, PxU32ToName>(inStream, "Flags");
++ inStream.createProperty<PvdSqHit, PxVec3>("Impact");
++ inStream.createProperty<PvdSqHit, PxVec3>("Normal");
++ inStream.createProperty<PvdSqHit, PxF32>("Distance");
++ inStream.createProperty<PvdSqHit, PxF32>("U");
++ inStream.createProperty<PvdSqHit, PxF32>("V");
++ }
++
++ void PvdMetaDataBinding::registerSDKProperties(PvdDataStream& inStream)
++ {
++ if (inStream.isClassExist<PxPhysics>())
++ return;
++ // PxPhysics
++ {
++ inStream.createClass<PxPhysics>();
++ PvdPropertyDefinitionHelper& helper(inStream.getPropertyDefinitionHelper());
++ PvdClassInfoDefine definitionObj(helper, getPvdNamespacedNameForType<PxPhysics>());
++ helper.pushName("TolerancesScale");
++ visitAllPvdProperties<PxTolerancesScale>(definitionObj);
++ helper.popName();
++ inStream.createProperty<PxPhysics, ObjectRef>("Scenes", "children", PropertyType::Array);
++ inStream.createProperty<PxPhysics, ObjectRef>("SharedShapes", "children", PropertyType::Array);
++ inStream.createProperty<PxPhysics, ObjectRef>("Materials", "children", PropertyType::Array);
++ inStream.createProperty<PxPhysics, ObjectRef>("HeightFields", "children", PropertyType::Array);
++ inStream.createProperty<PxPhysics, ObjectRef>("ConvexMeshes", "children", PropertyType::Array);
++ inStream.createProperty<PxPhysics, ObjectRef>("TriangleMeshes", "children", PropertyType::Array);
++ inStream.createProperty<PxPhysics, PxU32>("Version.Major");
++ inStream.createProperty<PxPhysics, PxU32>("Version.Minor");
++ inStream.createProperty<PxPhysics, PxU32>("Version.Bugfix");
++ inStream.createProperty<PxPhysics, String>("Version.Build");
++ definePropertyStruct<PxTolerancesScale, PxTolerancesScaleGeneratedValues, PxPhysics>(inStream, "TolerancesScale");
++ }
++ { // PxGeometry
++ inStream.createClass<PxGeometry>();
++ inStream.createProperty<PxGeometry, ObjectRef>("Shape", "parents", PropertyType::Scalar);
++ }
++ { // PxBoxGeometry
++ createClassDeriveAndDefineProperties<PxBoxGeometry, PxGeometry>(inStream);
++ definePropertyStruct<PxBoxGeometry, PxBoxGeometryGeneratedValues, PxBoxGeometry>(inStream);
++ }
++ { // PxSphereGeometry
++ createClassDeriveAndDefineProperties<PxSphereGeometry, PxGeometry>(inStream);
++ definePropertyStruct<PxSphereGeometry, PxSphereGeometryGeneratedValues, PxSphereGeometry>(inStream);
++ }
++ { // PxCapsuleGeometry
++ createClassDeriveAndDefineProperties<PxCapsuleGeometry, PxGeometry>(inStream);
++ definePropertyStruct<PxCapsuleGeometry, PxCapsuleGeometryGeneratedValues, PxCapsuleGeometry>(inStream);
++ }
++ { // PxPlaneGeometry
++ createClassDeriveAndDefineProperties<PxPlaneGeometry, PxGeometry>(inStream);
++ }
++ { // PxConvexMeshGeometry
++ createClassDeriveAndDefineProperties<PxConvexMeshGeometry, PxGeometry>(inStream);
++ definePropertyStruct<PxConvexMeshGeometry, PxConvexMeshGeometryGeneratedValues, PxConvexMeshGeometry>(inStream);
++ }
++
++ { // PxTetrahedronMeshGeometry
++ createClassDeriveAndDefineProperties<PxTetrahedronMeshGeometry, PxGeometry>(inStream);
++ definePropertyStruct<PxTetrahedronMeshGeometry, PxTetrahedronMeshGeometryGeneratedValues, PxTetrahedronMeshGeometry>(inStream);
++ }
++
++ { // PxTriangleMeshGeometry
++ createClassDeriveAndDefineProperties<PxTriangleMeshGeometry, PxGeometry>(inStream);
++ definePropertyStruct<PxTriangleMeshGeometry, PxTriangleMeshGeometryGeneratedValues, PxTriangleMeshGeometry>(inStream);
++ }
++ { // PxHeightFieldGeometry
++ createClassDeriveAndDefineProperties<PxHeightFieldGeometry, PxGeometry>(inStream);
++ definePropertyStruct<PxHeightFieldGeometry, PxHeightFieldGeometryGeneratedValues, PxHeightFieldGeometry>(inStream);
++ }
++ { // PxCustomGeometry
++ createClassDeriveAndDefineProperties<PxCustomGeometry, PxGeometry>(inStream);
++ definePropertyStruct<PxCustomGeometry, PxCustomGeometryGeneratedValues, PxCustomGeometry>(inStream);
++ }
++
++ // PxScene
++ {
++ // PT: TODO: why inline this for PvdContact but do PvdRaycast/etc in separate functions?
++ { // contact information
++ inStream.createClass<PvdContact>();
++ inStream.createProperty<PvdContact, PxVec3>("Point");
++ inStream.createProperty<PvdContact, PxVec3>("Axis");
++ inStream.createProperty<PvdContact, ObjectRef>("Shapes[0]");
++ inStream.createProperty<PvdContact, ObjectRef>("Shapes[1]");
++ inStream.createProperty<PvdContact, PxF32>("Separation");
++ inStream.createProperty<PvdContact, PxF32>("NormalForce");
++ inStream.createProperty<PvdContact, PxU32>("InternalFaceIndex[0]");
++ inStream.createProperty<PvdContact, PxU32>("InternalFaceIndex[1]");
++ inStream.createProperty<PvdContact, bool>("NormalForceValid");
++ }
++
++ registerPvdSqHit(inStream);
++ registerPvdRaycast(inStream);
++ registerPvdSweep(inStream);
++ registerPvdOverlap(inStream);
++
++ inStream.createClass<PxScene>();
++ PvdPropertyDefinitionHelper& helper(inStream.getPropertyDefinitionHelper());
++ PvdClassInfoDefine definitionObj(helper, getPvdNamespacedNameForType<PxScene>());
++ visitAllPvdProperties<PxSceneDesc>(definitionObj);
++ helper.pushName("SimulationStatistics");
++ visitAllPvdProperties<PxSimulationStatistics>(definitionObj);
++ helper.popName();
++ inStream.createProperty<PxScene, ObjectRef>("Physics", "parents", PropertyType::Scalar);
++ inStream.createProperty<PxScene, PxU32>("Timestamp");
++ inStream.createProperty<PxScene, PxReal>("SimulateElapsedTime");
++ definePropertyStruct<PxSceneDesc, PxSceneDescGeneratedValues, PxScene>(inStream);
++ definePropertyStruct<PxSimulationStatistics, PxSimulationStatisticsGeneratedValues, PxScene>(inStream, "SimulationStatistics");
++ inStream.createProperty<PxScene, PvdContact>("Contacts", "", PropertyType::Array);
++
++ inStream.createProperty<PxScene, PvdOverlap>("SceneQueries.Overlaps", "", PropertyType::Array);
++ inStream.createProperty<PxScene, PvdSweep>("SceneQueries.Sweeps", "", PropertyType::Array);
++ inStream.createProperty<PxScene, PvdSqHit>("SceneQueries.Hits", "", PropertyType::Array);
++ inStream.createProperty<PxScene, PvdRaycast>("SceneQueries.Raycasts", "", PropertyType::Array);
++ inStream.createProperty<PxScene, PxTransform>("SceneQueries.PoseList", "", PropertyType::Array);
++ inStream.createProperty<PxScene, PxFilterData>("SceneQueries.FilterDataList", "", PropertyType::Array);
++ inStream.createProperty<PxScene, ObjectRef>("SceneQueries.GeometryList", "", PropertyType::Array);
++
++ inStream.createProperty<PxScene, PvdOverlap>("BatchedQueries.Overlaps", "", PropertyType::Array);
++ inStream.createProperty<PxScene, PvdSweep>("BatchedQueries.Sweeps", "", PropertyType::Array);
++ inStream.createProperty<PxScene, PvdSqHit>("BatchedQueries.Hits", "", PropertyType::Array);
++ inStream.createProperty<PxScene, PvdRaycast>("BatchedQueries.Raycasts", "", PropertyType::Array);
++ inStream.createProperty<PxScene, PxTransform>("BatchedQueries.PoseList", "", PropertyType::Array);
++ inStream.createProperty<PxScene, PxFilterData>("BatchedQueries.FilterDataList", "", PropertyType::Array);
++ inStream.createProperty<PxScene, ObjectRef>("BatchedQueries.GeometryList", "", PropertyType::Array);
++
++ inStream.createProperty<PxScene, ObjectRef>("RigidStatics", "children", PropertyType::Array);
++ inStream.createProperty<PxScene, ObjectRef>("RigidDynamics", "children", PropertyType::Array);
++ inStream.createProperty<PxScene, ObjectRef>("Articulations", "children", PropertyType::Array);
++ inStream.createProperty<PxScene, ObjectRef>("Joints", "children", PropertyType::Array);
++ inStream.createProperty<PxScene, ObjectRef>("Aggregates", "children", PropertyType::Array);
++ }
++ // PxMaterial
++ {
++ createClassAndDefineProperties<PxMaterial>(inStream);
++ definePropertyStruct<PxMaterial, PxMaterialGeneratedValues, PxMaterial>(inStream);
++ inStream.createProperty<PxMaterial, ObjectRef>("Physics", "parents", PropertyType::Scalar);
++ }
++ // PxHeightField
++ {
++ {
++ inStream.createClass<PxHeightFieldSample>();
++ inStream.createProperty<PxHeightFieldSample, PxU16>("Height");
++ inStream.createProperty<PxHeightFieldSample, PxU8>("MaterialIndex[0]");
++ inStream.createProperty<PxHeightFieldSample, PxU8>("MaterialIndex[1]");
++ }
++
++ inStream.createClass<PxHeightField>();
++ // It is important the PVD fields match the RepX fields, so this has
++ // to be hand coded.
++ PvdPropertyDefinitionHelper& helper(inStream.getPropertyDefinitionHelper());
++ PvdClassInfoDefine definitionObj(helper, getPvdNamespacedNameForType<PxHeightField>());
++ visitAllPvdProperties<PxHeightFieldDesc>(definitionObj);
++ inStream.createProperty<PxHeightField, PxHeightFieldSample>("Samples", "", PropertyType::Array);
++ inStream.createProperty<PxHeightField, ObjectRef>("Physics", "parents", PropertyType::Scalar);
++ definePropertyStruct<PxHeightFieldDesc, PxHeightFieldDescGeneratedValues, PxHeightField>(inStream);
++ }
++ // PxConvexMesh
++ {
++ { // hull polygon data.
++ inStream.createClass<PvdHullPolygonData>();
++ inStream.createProperty<PvdHullPolygonData, PxU16>("NumVertices");
++ inStream.createProperty<PvdHullPolygonData, PxU16>("IndexBase");
++ }
++ inStream.createClass<PxConvexMesh>();
++ inStream.createProperty<PxConvexMesh, PxF32>("Mass");
++ inStream.createProperty<PxConvexMesh, PxMat33>("LocalInertia");
++ inStream.createProperty<PxConvexMesh, PxVec3>("LocalCenterOfMass");
++ inStream.createProperty<PxConvexMesh, PxVec3>("Points", "", PropertyType::Array);
++ inStream.createProperty<PxConvexMesh, PvdHullPolygonData>("HullPolygons", "", PropertyType::Array);
++ inStream.createProperty<PxConvexMesh, PxU8>("PolygonIndexes", "", PropertyType::Array);
++ inStream.createProperty<PxConvexMesh, ObjectRef>("Physics", "parents", PropertyType::Scalar);
++ }
++ // PxTriangleMesh
++ {
++ inStream.createClass<PxTriangleMesh>();
++ inStream.createProperty<PxTriangleMesh, PxVec3>("Points", "", PropertyType::Array);
++ inStream.createProperty<PxTriangleMesh, PxU32>("NbTriangles", "", PropertyType::Scalar);
++ inStream.createProperty<PxTriangleMesh, PxU32>("Triangles", "", PropertyType::Array);
++ inStream.createProperty<PxTriangleMesh, PxU16>("MaterialIndices", "", PropertyType::Array);
++ inStream.createProperty<PxTriangleMesh, ObjectRef>("Physics", "parents", PropertyType::Scalar);
++ }
++
++ // PxTetrahedronMesh
++ {
++ inStream.createClass<PxTetrahedronMesh>();
++ inStream.createProperty<PxTetrahedronMesh, PxVec3>("Points", "", PropertyType::Array);
++ inStream.createProperty<PxTetrahedronMesh, PxU32>("NbTriangles", "", PropertyType::Scalar);
++ inStream.createProperty<PxTetrahedronMesh, PxU32>("Triangles", "", PropertyType::Array);
++ inStream.createProperty<PxTetrahedronMesh, ObjectRef>("Physics", "parents", PropertyType::Scalar);
++ }
++
++ // PxDeformableSurfaceMaterial
++ {
++ createClassAndDefineProperties<PxDeformableSurfaceMaterial>(inStream);
++ definePropertyStruct<PxDeformableSurfaceMaterial, PxDeformableSurfaceMaterialGeneratedValues, PxDeformableSurfaceMaterial>(inStream);
++ inStream.createProperty<PxDeformableSurfaceMaterial, ObjectRef>("Physics", "parents", PropertyType::Scalar);
++ }
++
++ // PxDeformableVolumeMaterial
++ {
++ createClassAndDefineProperties<PxDeformableVolumeMaterial>(inStream);
++ definePropertyStruct<PxDeformableVolumeMaterial, PxDeformableVolumeMaterialGeneratedValues, PxDeformableVolumeMaterial>(inStream);
++ inStream.createProperty<PxDeformableVolumeMaterial, ObjectRef>("Physics", "parents", PropertyType::Scalar);
++ }
++
++ { // PxShape
++ createClassAndDefineProperties<PxShape>(inStream);
++ definePropertyStruct<PxShape, PxShapeGeneratedValues, PxShape>(inStream);
++ inStream.createProperty<PxShape, ObjectRef>("Geometry", "children");
++ inStream.createProperty<PxShape, ObjectRef>("Materials", "children", PropertyType::Array);
++ inStream.createProperty<PxShape, ObjectRef>("Actor", "parents");
++ }
++ // PxActor
++ {
++ createClassAndDefineProperties<PxActor>(inStream);
++ inStream.createProperty<PxActor, ObjectRef>("Scene", "parents");
++ }
++ // PxRigidActor
++ {
++ createClassDeriveAndDefineProperties<PxRigidActor, PxActor>(inStream);
++ inStream.createProperty<PxRigidActor, ObjectRef>("Shapes", "children", PropertyType::Array);
++ inStream.createProperty<PxRigidActor, ObjectRef>("Joints", "children", PropertyType::Array);
++ }
++ // PxRigidStatic
++ {
++ createClassDeriveAndDefineProperties<PxRigidStatic, PxRigidActor>(inStream);
++ definePropertyStruct<PxRigidStatic, PxRigidStaticGeneratedValues, PxRigidStatic>(inStream);
++ }
++ { // PxRigidBody
++ createClassDeriveAndDefineProperties<PxRigidBody, PxRigidActor>(inStream);
++ }
++ // PxRigidDynamic
++ {
++ createClassDeriveAndDefineProperties<PxRigidDynamic, PxRigidBody>(inStream);
++ // If anyone adds a 'getKinematicTarget' to PxRigidDynamic you can remove the line
++ // below (after the code generator has run).
++ inStream.createProperty<PxRigidDynamic, PxTransform>("KinematicTarget");
++ definePropertyStruct<PxRigidDynamic, PxRigidDynamicGeneratedValues, PxRigidDynamic>(inStream);
++ // Manually define the update struct.
++ PvdPropertyDefinitionHelper& helper(inStream.getPropertyDefinitionHelper());
++ /*struct PxRigidDynamicUpdateBlock
++ {
++ Transform GlobalPose;
++ Float3 LinearVelocity;
++ Float3 AngularVelocity;
++ PxU8 IsSleeping;
++ PxU8 padding[3];
++ };
++ */
++ helper.pushName("GlobalPose");
++ helper.addPropertyMessageArg<PxTransform>(PX_OFFSET_OF_RT(PxRigidDynamicUpdateBlock, GlobalPose));
++ helper.popName();
++ helper.pushName("LinearVelocity");
++ helper.addPropertyMessageArg<PxVec3>(PX_OFFSET_OF_RT(PxRigidDynamicUpdateBlock, LinearVelocity));
++ helper.popName();
++ helper.pushName("AngularVelocity");
++ helper.addPropertyMessageArg<PxVec3>(PX_OFFSET_OF_RT(PxRigidDynamicUpdateBlock, AngularVelocity));
++ helper.popName();
++ helper.pushName("IsSleeping");
++ helper.addPropertyMessageArg<bool>(PX_OFFSET_OF_RT(PxRigidDynamicUpdateBlock, IsSleeping));
++ helper.popName();
++ helper.addPropertyMessage<PxRigidDynamic, PxRigidDynamicUpdateBlock>();
++ }
++
++ // PxArticulationReducedCoordinate
++ {
++ createClassAndDefineProperties<PxArticulationReducedCoordinate>(inStream);
++ inStream.createProperty<PxArticulationReducedCoordinate, ObjectRef>("Scene", "parents");
++ inStream.createProperty<PxArticulationReducedCoordinate, ObjectRef>("Links", "children", PropertyType::Array);
++ definePropertyStruct<PxArticulationReducedCoordinate, PxArticulationReducedCoordinateGeneratedValues, PxArticulationReducedCoordinate>(inStream);
++ }
++
++ { // PxArticulationLink
++ createClassDeriveAndDefineProperties<PxArticulationLink, PxRigidBody>(inStream);
++ inStream.createProperty<PxArticulationLink, ObjectRef>("Parent", "parents");
++ inStream.createProperty<PxArticulationLink, ObjectRef>("Links", "children", PropertyType::Array);
++ inStream.createProperty<PxArticulationLink, ObjectRef>("InboundJoint", "children");
++ definePropertyStruct<PxArticulationLink, PxArticulationLinkGeneratedValues, PxArticulationLink>(inStream);
++
++ PvdPropertyDefinitionHelper& helper(inStream.getPropertyDefinitionHelper());
++ /*struct PxArticulationLinkUpdateBlock
++ {
++ Transform GlobalPose;
++ Float3 LinearVelocity;
++ Float3 AngularVelocity;
++ };*/
++
++ helper.pushName("GlobalPose");
++ helper.addPropertyMessageArg<PxTransform>(PX_OFFSET_OF(PxArticulationLinkUpdateBlock, GlobalPose));
++ helper.popName();
++ helper.pushName("LinearVelocity");
++ helper.addPropertyMessageArg<PxVec3>(PX_OFFSET_OF(PxArticulationLinkUpdateBlock, LinearVelocity));
++ helper.popName();
++ helper.pushName("AngularVelocity");
++ helper.addPropertyMessageArg<PxVec3>(PX_OFFSET_OF(PxArticulationLinkUpdateBlock, AngularVelocity));
++ helper.popName();
++ helper.addPropertyMessage<PxArticulationLink, PxArticulationLinkUpdateBlock>();
++
++ }
++ { // PxArticulationJoint
++ createClassAndDefineProperties<PxArticulationJointReducedCoordinate>(inStream);
++ inStream.createProperty<PxArticulationJointReducedCoordinate, ObjectRef>("Link", "parents");
++ definePropertyStruct<PxArticulationJointReducedCoordinate, PxArticulationJointReducedCoordinateGeneratedValues, PxArticulationJointReducedCoordinate>(inStream);
++
++ PvdPropertyDefinitionHelper& helper(inStream.getPropertyDefinitionHelper());
++
++ helper.pushName("JointPosition[eX]");
++ helper.addPropertyMessageArg<PxReal>(PX_OFFSET_OF(PxArticulationJointUpdateBlock, JointPosition_eX));
++ helper.popName();
++ helper.pushName("JointPosition[eY]");
++ helper.addPropertyMessageArg<PxReal>(PX_OFFSET_OF(PxArticulationJointUpdateBlock, JointPosition_eY));
++ helper.popName();
++ helper.pushName("JointPosition[eZ]");
++ helper.addPropertyMessageArg<PxReal>(PX_OFFSET_OF(PxArticulationJointUpdateBlock, JointPosition_eZ));
++ helper.popName();
++ helper.pushName("JointPosition[eTWIST]");
++ helper.addPropertyMessageArg<PxReal>(PX_OFFSET_OF(PxArticulationJointUpdateBlock, JointPosition_eTwist));
++ helper.popName();
++ helper.pushName("JointPosition[eSWING1]");
++ helper.addPropertyMessageArg<PxReal>(PX_OFFSET_OF(PxArticulationJointUpdateBlock, JointPosition_eSwing1));
++ helper.popName();
++ helper.pushName("JointPosition[eSWING2]");
++ helper.addPropertyMessageArg<PxReal>(PX_OFFSET_OF(PxArticulationJointUpdateBlock, JointPosition_eSwing2));
++ helper.popName();
++
++ helper.pushName("JointVelocity[eX]");
++ helper.addPropertyMessageArg<PxReal>(PX_OFFSET_OF(PxArticulationJointUpdateBlock, JointVelocity_eX));
++ helper.popName();
++ helper.pushName("JointVelocity[eY]");
++ helper.addPropertyMessageArg<PxReal>(PX_OFFSET_OF(PxArticulationJointUpdateBlock, JointVelocity_eY));
++ helper.popName();
++ helper.pushName("JointVelocity[eZ]");
++ helper.addPropertyMessageArg<PxReal>(PX_OFFSET_OF(PxArticulationJointUpdateBlock, JointVelocity_eZ));
++ helper.popName();
++ helper.pushName("JointVelocity[eTWIST]");
++ helper.addPropertyMessageArg<PxReal>(PX_OFFSET_OF(PxArticulationJointUpdateBlock, JointVelocity_eTwist));
++ helper.popName();
++ helper.pushName("JointVelocity[eSWING1]");
++ helper.addPropertyMessageArg<PxReal>(PX_OFFSET_OF(PxArticulationJointUpdateBlock, JointVelocity_eSwing1));
++ helper.popName();
++ helper.pushName("JointVelocity[eSWING2]");
++ helper.addPropertyMessageArg<PxReal>(PX_OFFSET_OF(PxArticulationJointUpdateBlock, JointVelocity_eSwing2));
++ helper.popName();
++
++ helper.addPropertyMessage<PxArticulationJointReducedCoordinate, PxArticulationJointUpdateBlock>();
++ }
++ { // PxConstraint
++ createClassAndDefineProperties<PxConstraint>(inStream);
++ definePropertyStruct<PxConstraint, PxConstraintGeneratedValues, PxConstraint>(inStream);
++ }
++ {
++ // PxAggregate
++ createClassAndDefineProperties<PxAggregate>(inStream);
++ inStream.createProperty<PxAggregate, ObjectRef>("Scene", "parents");
++ definePropertyStruct<PxAggregate, PxAggregateGeneratedValues, PxAggregate>(inStream);
++ inStream.createProperty<PxAggregate, ObjectRef>("Actors", "children", PropertyType::Array);
++ inStream.createProperty<PxAggregate, ObjectRef>("Articulations", "children", PropertyType::Array);
++ }
++ }
++
++ template <typename TClassType, typename TValueType, typename TDataType>
++ static void doSendAllProperties(PvdDataStream& inStream, const TDataType* inDatatype, const void* instanceId)
++ {
++ TValueType theValues(inDatatype);
++ inStream.setPropertyMessage(instanceId, theValues);
++ }
++
++ void PvdMetaDataBinding::sendAllProperties(PvdDataStream& inStream, const PxPhysics& inPhysics)
++ {
++ PxTolerancesScale theScale(inPhysics.getTolerancesScale());
++ doSendAllProperties<PxPhysics, PxTolerancesScaleGeneratedValues>(inStream, &theScale, &inPhysics);
++ inStream.setPropertyValue(&inPhysics, "Version.Major", PxU32(PX_PHYSICS_VERSION_MAJOR));
++ inStream.setPropertyValue(&inPhysics, "Version.Minor", PxU32(PX_PHYSICS_VERSION_MINOR));
++ inStream.setPropertyValue(&inPhysics, "Version.Bugfix", PxU32(PX_PHYSICS_VERSION_BUGFIX));
++
++ #if PX_DEBUG
++ String buildType = "Debug";
++ #elif PX_CHECKED
++ String buildType = "Checked";
++ #elif PX_PROFILE
++ String buildType = "Profile";
++ #else
++ String buildType = "Release";
++ #endif
++ inStream.setPropertyValue(&inPhysics, "Version.Build", buildType);
++ }
++
++ void PvdMetaDataBinding::sendAllProperties(PvdDataStream& inStream, const PxScene& inScene)
++ {
++ const PxPhysics& physics(const_cast<PxScene&>(inScene).getPhysics());
++ PxTolerancesScale theScale;
++ PxSceneDesc theDesc(theScale);
++
++ {
++ // setDominanceGroupPair ?
++
++ theDesc.gravity = inScene.getGravity();
++ theDesc.simulationEventCallback = inScene.getSimulationEventCallback();
++ theDesc.contactModifyCallback = inScene.getContactModifyCallback();
++ theDesc.ccdContactModifyCallback = inScene.getCCDContactModifyCallback();
++ theDesc.filterShaderData = inScene.getFilterShaderData();
++ theDesc.filterShaderDataSize = inScene.getFilterShaderDataSize();
++ theDesc.filterShader = inScene.getFilterShader();
++ theDesc.filterCallback = inScene.getFilterCallback();
++ // PxPairFilteringMode::Enum KineKineFilteringMode;
++ // PxPairFilteringMode::Enum StaticKineFilteringMode;
++ theDesc.broadPhaseType = inScene.getBroadPhaseType();
++ theDesc.broadPhaseCallback = inScene.getBroadPhaseCallback();
++ theDesc.limits = inScene.getLimits();
++ theDesc.frictionType = inScene.getFrictionType();
++ // PxSolverType::Enum SolverType;
++ theDesc.bounceThresholdVelocity = inScene.getBounceThresholdVelocity();
++ theDesc.frictionOffsetThreshold = inScene.getFrictionOffsetThreshold();
++ theDesc.frictionCorrelationDistance = inScene.getFrictionCorrelationDistance();
++ theDesc.flags = inScene.getFlags();
++ theDesc.cpuDispatcher = inScene.getCpuDispatcher();
++ theDesc.cudaContextManager = inScene.getCudaContextManager();
++ theDesc.staticStructure = inScene.getStaticStructure();
++ theDesc.dynamicStructure = inScene.getDynamicStructure();
++ theDesc.dynamicTreeRebuildRateHint = inScene.getDynamicTreeRebuildRateHint();
++ theDesc.sceneQueryUpdateMode = inScene.getSceneQueryUpdateMode();
++ theDesc.userData = inScene.userData;
++ theDesc.solverBatchSize = inScene.getSolverBatchSize();
++ theDesc.solverArticulationBatchSize = inScene.getSolverArticulationBatchSize();
++ // PxU32 NbContactDataBlocks;
++ // PxU32 MaxNbContactDataBlocks;
++ // theDesc.nbContactDataBlocks = inScene.getNbContactDataBlocksUsed();
++ // theDesc.maxNbContactDataBlocks = inScene.getMaxNbContactDataBlocksUsed();
++ theDesc.maxBiasCoefficient = inScene.getMaxBiasCoefficient();
++ theDesc.contactReportStreamBufferSize = inScene.getContactReportStreamBufferSize();
++ theDesc.ccdMaxPasses = inScene.getCCDMaxPasses();
++ theDesc.ccdThreshold = inScene.getCCDThreshold();
++ theDesc.ccdMaxSeparation = inScene.getCCDMaxSeparation();
++ // theDesc.simulationOrder = inScene.getSimulationOrder();
++ theDesc.wakeCounterResetValue = inScene.getWakeCounterResetValue();
++
++ theDesc.gpuDynamicsConfig = inScene.getGpuDynamicsConfig();
++ // PxBounds3 SanityBounds;
++ // PxGpuDynamicsMemoryConfig GpuDynamicsConfig;
++ // PxU32 GpuMaxNumPartitions;
++ // PxU32 GpuComputeVersion;
++ // PxReal BroadPhaseInflation;
++ // PxU32 ContactPairSlabSize;
++ }
++
++ PxSceneDescGeneratedValues theValues(&theDesc);
++ inStream.setPropertyMessage(&inScene, theValues);
++ // Create parent/child relationship.
++ inStream.setPropertyValue(&inScene, "Physics", reinterpret_cast<const void*>(&physics));
++ inStream.pushBackObjectRef(&physics, "Scenes", &inScene);
++ }
++
++ void PvdMetaDataBinding::sendBeginFrame(PvdDataStream& inStream, const PxScene* inScene, PxReal simulateElapsedTime)
++ {
++ inStream.beginSection(inScene, "frame");
++ inStream.setPropertyValue(inScene, "Timestamp", inScene->getTimestamp());
++ inStream.setPropertyValue(inScene, "SimulateElapsedTime", simulateElapsedTime);
++ }
++
++ template <typename TDataType>
++ struct NullConverter
++ {
++ void operator()(TDataType& data, const TDataType& src)
++ {
++ data = src;
++ }
++ };
++
++ template <typename TTargetType, PxU32 T_NUM_ITEMS, typename TSourceType = TTargetType,
++ typename Converter = NullConverter<TTargetType> >
++ class ScopedPropertyValueSender
++ {
++ TTargetType mStack[T_NUM_ITEMS];
++ TTargetType* mCur;
++ const TTargetType* mEnd;
++ PvdDataStream& mStream;
++
++ public:
++ ScopedPropertyValueSender(PvdDataStream& inStream, const void* inObj, String name)
++ : mCur(mStack), mEnd(&mStack[T_NUM_ITEMS]), mStream(inStream)
++ {
++ mStream.beginSetPropertyValue(inObj, name, getPvdNamespacedNameForType<TTargetType>());
++ }
++
++ ~ScopedPropertyValueSender()
++ {
++ if(mStack != mCur)
++ {
++ PxU32 size = sizeof(TTargetType) * PxU32(mCur - mStack);
++ mStream.appendPropertyValueData(DataRef<const PxU8>(reinterpret_cast<PxU8*>(mStack), size));
++ }
++ mStream.endSetPropertyValue();
++ }
++
++ void append(const TSourceType& data)
++ {
++ Converter()(*mCur, data);
++ if(mCur < mEnd - 1)
++ ++mCur;
++ else
++ {
++ mStream.appendPropertyValueData(DataRef<const PxU8>(reinterpret_cast<PxU8*>(mStack), sizeof mStack));
++ mCur = mStack;
++ }
++ }
++
++ private:
++ ScopedPropertyValueSender& operator=(const ScopedPropertyValueSender&);
++ };
++
++ void PvdMetaDataBinding::sendContacts(PvdDataStream& inStream, const PxScene& inScene)
++ {
++ inStream.setPropertyValue(&inScene, "Contacts", DataRef<const PxU8>(), getPvdNamespacedNameForType<PvdContact>());
++ }
++
++ void PvdMetaDataBinding::sendStats(PvdDataStream& inStream, const PxScene* inScene)
++ {
++ PxSimulationStatistics theStats;
++ inScene->getSimulationStatistics(theStats);
++
++ PxSimulationStatisticsGeneratedValues values(&theStats);
++ inStream.setPropertyMessage(inScene, values);
++ }
++
++ struct PvdContactConverter
++ {
++ void operator()(PvdContact& data, const Sc::Contact& src)
++ {
++ data.point = src.point;
++ data.axis = src.normal;
++ data.shape0 = src.shape0;
++ data.shape1 = src.shape1;
++ data.separation = src.separation;
++ data.normalForce = src.normalForce;
++ data.internalFaceIndex0 = src.faceIndex0;
++ data.internalFaceIndex1 = src.faceIndex1;
++ data.normalForceAvailable = src.normalForceAvailable;
++ }
++ };
++
++ void PvdMetaDataBinding::sendContacts(PvdDataStream& inStream, const PxScene& inScene, PxArray<Contact>& inContacts)
++ {
++ ScopedPropertyValueSender<PvdContact, 32, Sc::Contact, PvdContactConverter> sender(inStream, &inScene, "Contacts");
++
++ for(PxU32 i = 0; i < inContacts.size(); i++)
++ {
++ sender.append(inContacts[i]);
++ }
++ }
++
++ void PvdMetaDataBinding::sendEndFrame(PvdDataStream& inStream, const PxScene* inScene)
++ {
++ //flush other client
++ inStream.endSection(inScene, "frame");
++ }
++
++ template <typename TDataType>
++ static void addPhysicsGroupProperty(PvdDataStream& inStream, const char* groupName, const TDataType& inData, const PxPhysics& ownerPhysics)
++ {
++ inStream.setPropertyValue(&inData, "Physics", reinterpret_cast<const void*>(&ownerPhysics));
++ inStream.pushBackObjectRef(&ownerPhysics, groupName, &inData);
++ // Buffer type objects *have* to be flushed directly out once created else scene creation doesn't work.
++ }
++
++ template <typename TDataType>
++ static void removePhysicsGroupProperty(PvdDataStream& inStream, const char* groupName, const TDataType& inData, const PxPhysics& ownerPhysics)
++ {
++ inStream.removeObjectRef(&ownerPhysics, groupName, &inData);
++ inStream.destroyInstance(&inData);
++ }
++
++ void PvdMetaDataBinding::createInstance(PvdDataStream& inStream, const PxMaterial& inMaterial, const PxPhysics& ownerPhysics)
++ {
++ inStream.createInstance(&inMaterial);
++ sendAllProperties(inStream, inMaterial);
++ addPhysicsGroupProperty(inStream, "Materials", inMaterial, ownerPhysics);
++ }
++
++ void PvdMetaDataBinding::sendAllProperties(PvdDataStream& inStream, const PxMaterial& inMaterial)
++ {
++ PxMaterialGeneratedValues values(&inMaterial);
++ inStream.setPropertyMessage(&inMaterial, values);
++ }
++
++ void PvdMetaDataBinding::destroyInstance(PvdDataStream& inStream, const PxMaterial& inMaterial, const PxPhysics& ownerPhysics)
++ {
++ removePhysicsGroupProperty(inStream, "Materials", inMaterial, ownerPhysics);
++ }
++
++ void PvdMetaDataBinding::createInstance(PvdDataStream& inStream, const PxDeformableSurfaceMaterial& inMaterial, const PxPhysics& ownerPhysics)
++ {
++ inStream.createInstance(&inMaterial);
++ sendAllProperties(inStream, inMaterial);
++ addPhysicsGroupProperty(inStream, "FEMMaterials", inMaterial, ownerPhysics);
++ }
++
++ void PvdMetaDataBinding::sendAllProperties(PvdDataStream& /*inStream*/, const PxDeformableSurfaceMaterial& /*inMaterial*/)
++ {
++ /*PxMaterialGeneratedValues values(&inMaterial);
++ inStream.setPropertyMessage(&inMaterial, values);*/
++ }
++
++ void PvdMetaDataBinding::destroyInstance(PvdDataStream& /*inStream*/, const PxDeformableSurfaceMaterial& /*inMaterial*/, const PxPhysics& /*ownerPhysics*/)
++ {
++ //removePhysicsGroupProperty(inStream, "Materials", inMaterial, ownerPhysics);
++ }
++
++ void PvdMetaDataBinding::createInstance(PvdDataStream& inStream, const PxDeformableVolumeMaterial& inMaterial, const PxPhysics& ownerPhysics)
++ {
++ inStream.createInstance(&inMaterial);
++ sendAllProperties(inStream, inMaterial);
++ addPhysicsGroupProperty(inStream, "FEMMaterials", inMaterial, ownerPhysics);
++ }
++
++ void PvdMetaDataBinding::sendAllProperties(PvdDataStream& /*inStream*/, const PxDeformableVolumeMaterial& /*inMaterial*/)
++ {
++ /*PxMaterialGeneratedValues values(&inMaterial);
++ inStream.setPropertyMessage(&inMaterial, values);*/
++ }
++
++ void PvdMetaDataBinding::destroyInstance(PvdDataStream& /*inStream*/, const PxDeformableVolumeMaterial& /*inMaterial*/, const PxPhysics& /*ownerPhysics*/)
++ {
++ //removePhysicsGroupProperty(inStream, "Materials", inMaterial, ownerPhysics);
++ }
++
++ void PvdMetaDataBinding::createInstance(PvdDataStream& inStream, const PxPBDMaterial& inMaterial, const PxPhysics& ownerPhysics)
++ {
++ inStream.createInstance(&inMaterial);
++ sendAllProperties(inStream, inMaterial);
++ addPhysicsGroupProperty(inStream, "PBDMaterials", inMaterial, ownerPhysics);
++ }
++
++ void PvdMetaDataBinding::sendAllProperties(PvdDataStream& /*inStream*/, const PxPBDMaterial& /*inMaterial*/)
++ {
++ /*PxMaterialGeneratedValues values(&inMaterial);
++ inStream.setPropertyMessage(&inMaterial, values);*/
++ }
++
++ void PvdMetaDataBinding::destroyInstance(PvdDataStream& /*inStream*/, const PxPBDMaterial& /*inMaterial*/, const PxPhysics& /*ownerPhysics*/)
++ {
++ //removePhysicsGroupProperty(inStream, "Materials", inMaterial, ownerPhysics);
++ }
++
++ void PvdMetaDataBinding::sendAllProperties(PvdDataStream& inStream, const PxHeightField& inData)
++ {
++ PxHeightFieldDesc theDesc;
++ // Save the height field to desc.
++ theDesc.nbRows = inData.getNbRows();
++ theDesc.nbColumns = inData.getNbColumns();
++ theDesc.format = inData.getFormat();
++ theDesc.samples.stride = inData.getSampleStride();
++ theDesc.samples.data = NULL;
++ theDesc.convexEdgeThreshold = inData.getConvexEdgeThreshold();
++ theDesc.flags = inData.getFlags();
++
++ PxU32 theCellCount = inData.getNbRows() * inData.getNbColumns();
++ PxU32 theSampleStride = sizeof(PxHeightFieldSample);
++ PxU32 theSampleBufSize = theCellCount * theSampleStride;
++ mBindingData->mTempU8Array.resize(theSampleBufSize);
++ PxHeightFieldSample* theSamples = reinterpret_cast<PxHeightFieldSample*>(mBindingData->mTempU8Array.begin());
++ inData.saveCells(theSamples, theSampleBufSize);
++ theDesc.samples.data = theSamples;
++ PxHeightFieldDescGeneratedValues values(&theDesc);
++ inStream.setPropertyMessage(&inData, values);
++ PxHeightFieldSample* theSampleData = reinterpret_cast<PxHeightFieldSample*>(mBindingData->mTempU8Array.begin());
++ inStream.setPropertyValue(&inData, "Samples", theSampleData, theCellCount);
++ }
++
++ void PvdMetaDataBinding::createInstance(PvdDataStream& inStream, const PxHeightField& inData, const PxPhysics& ownerPhysics)
++ {
++ inStream.createInstance(&inData);
++ sendAllProperties(inStream, inData);
++ addPhysicsGroupProperty(inStream, "HeightFields", inData, ownerPhysics);
++ }
++
++ void PvdMetaDataBinding::destroyInstance(PvdDataStream& inStream, const PxHeightField& inData, const PxPhysics& ownerPhysics)
++ {
++ removePhysicsGroupProperty(inStream, "HeightFields", inData, ownerPhysics);
++ }
++
++ void PvdMetaDataBinding::createInstance(PvdDataStream& inStream, const PxConvexMesh& inData, const PxPhysics& ownerPhysics)
++ {
++ inStream.createInstance(&inData);
++ PxReal mass;
++ PxMat33 localInertia;
++ PxVec3 localCom;
++ inData.getMassInformation(mass, localInertia, localCom);
++ inStream.setPropertyValue(&inData, "Mass", mass);
++ inStream.setPropertyValue(&inData, "LocalInertia", localInertia);
++ inStream.setPropertyValue(&inData, "LocalCenterOfMass", localCom);
++
++ // update arrays:
++ // vertex Array:
++ {
++ const PxVec3* vertexPtr = inData.getVertices();
++ const PxU32 numVertices = inData.getNbVertices();
++ inStream.setPropertyValue(&inData, "Points", vertexPtr, numVertices);
++ }
++
++ // HullPolyArray:
++ PxU16 maxIndices = 0;
++ {
++
++ PxU32 numPolygons = inData.getNbPolygons();
++ PvdHullPolygonData* tempData = mBindingData->allocateTemp<PvdHullPolygonData>(numPolygons);
++ // Get the polygon data stripping the plane equations
++ for(PxU32 index = 0; index < numPolygons; index++)
++ {
++ PxHullPolygon curOut;
++ inData.getPolygonData(index, curOut);
++ maxIndices = PxMax(maxIndices, PxU16(curOut.mIndexBase + curOut.mNbVerts));
++ tempData[index].mIndexBase = curOut.mIndexBase;
++ tempData[index].mNumVertices = curOut.mNbVerts;
++ }
++ inStream.setPropertyValue(&inData, "HullPolygons", tempData, numPolygons);
++ }
++
++ // poly index Array:
++ {
++ const PxU8* indices = inData.getIndexBuffer();
++ inStream.setPropertyValue(&inData, "PolygonIndexes", indices, maxIndices);
++ }
++ addPhysicsGroupProperty(inStream, "ConvexMeshes", inData, ownerPhysics);
++ }
++
++ void PvdMetaDataBinding::destroyInstance(PvdDataStream& inStream, const PxConvexMesh& inData, const PxPhysics& ownerPhysics)
++ {
++ removePhysicsGroupProperty(inStream, "ConvexMeshes", inData, ownerPhysics);
++ }
++
++ void PvdMetaDataBinding::createInstance(PvdDataStream& inStream, const PxTetrahedronMesh& inData, const PxPhysics& ownerPhysics)
++ {
++ inStream.createInstance(&inData);
++
++ // vertex Array:
++ {
++ const PxVec3* vertexPtr = inData.getVertices();
++ const PxU32 numVertices = inData.getNbVertices();
++ inStream.setPropertyValue(&inData, "Vertices", vertexPtr, numVertices);
++ }
++
++ ////invert mass array
++ //{
++ // const float* invMassPtr = inData.getVertInvMasses();
++ // const PxU32 numVertices = inData.getCollisionMesh().getNbVertices();
++ // inStream.setPropertyValue(&inData, "invert mass", invMassPtr, numVertices);
++ //}
++
++ // index Array:
++ {
++ const bool has16BitIndices = inData.getTetrahedronMeshFlags() & PxTetrahedronMeshFlag::e16_BIT_INDICES ? true : false;
++ const PxU32 numTetrahedrons = inData.getNbTetrahedrons();
++
++ inStream.setPropertyValue(&inData, "NbTetrahedron", numTetrahedrons);
++
++ const PxU32 numIndexes = numTetrahedrons * 4;
++ const PxU8* tetrahedronsPtr = reinterpret_cast<const PxU8*>(inData.getTetrahedrons());
++ // We declared this type as a 32 bit integer above.
++ // PVD will automatically unsigned-extend data that is smaller than the target type.
++ if (has16BitIndices)
++ inStream.setPropertyValue(&inData, "Tetrahedrons", reinterpret_cast<const PxU16*>(tetrahedronsPtr), numIndexes);
++ else
++ inStream.setPropertyValue(&inData, "Tetrahedrons", reinterpret_cast<const PxU32*>(tetrahedronsPtr), numIndexes);
++ }
++
++ addPhysicsGroupProperty(inStream, "TetrahedronMeshes", inData, ownerPhysics);
++ }
++
++ void PvdMetaDataBinding::destroyInstance(PvdDataStream& inStream, const PxTetrahedronMesh& inData, const PxPhysics& ownerPhysics)
++ {
++ removePhysicsGroupProperty(inStream, "TetrahedronMeshes", inData, ownerPhysics);
++ }
++
++ void PvdMetaDataBinding::createInstance(PvdDataStream& inStream, const PxTriangleMesh& inData, const PxPhysics& ownerPhysics)
++ {
++ inStream.createInstance(&inData);
++ bool hasMatIndex = inData.getTriangleMaterialIndex(0) != 0xffff;
++ // update arrays:
++ // vertex Array:
++ {
++ const PxVec3* vertexPtr = inData.getVertices();
++ const PxU32 numVertices = inData.getNbVertices();
++ inStream.setPropertyValue(&inData, "Points", vertexPtr, numVertices);
++ }
++
++ // index Array:
++ {
++ const bool has16BitIndices = inData.getTriangleMeshFlags() & PxTriangleMeshFlag::e16_BIT_INDICES ? true : false;
++ const PxU32 numTriangles = inData.getNbTriangles();
++
++ inStream.setPropertyValue(&inData, "NbTriangles", numTriangles);
++
++ const PxU32 numIndexes = numTriangles * 3;
++ const PxU8* trianglePtr = reinterpret_cast<const PxU8*>(inData.getTriangles());
++ // We declared this type as a 32 bit integer above.
++ // PVD will automatically unsigned-extend data that is smaller than the target type.
++ if(has16BitIndices)
++ inStream.setPropertyValue(&inData, "Triangles", reinterpret_cast<const PxU16*>(trianglePtr), numIndexes);
++ else
++ inStream.setPropertyValue(&inData, "Triangles", reinterpret_cast<const PxU32*>(trianglePtr), numIndexes);
++ }
++
++ // material Array:
++ if(hasMatIndex)
++ {
++ PxU32 numMaterials = inData.getNbTriangles();
++ PxU16* matIndexData = mBindingData->allocateTemp<PxU16>(numMaterials);
++ for(PxU32 m = 0; m < numMaterials; m++)
++ matIndexData[m] = inData.getTriangleMaterialIndex(m);
++ inStream.setPropertyValue(&inData, "MaterialIndices", matIndexData, numMaterials);
++ }
++ addPhysicsGroupProperty(inStream, "TriangleMeshes", inData, ownerPhysics);
++ }
++
++ void PvdMetaDataBinding::destroyInstance(PvdDataStream& inStream, const PxTriangleMesh& inData, const PxPhysics& ownerPhysics)
++ {
++ removePhysicsGroupProperty(inStream, "TriangleMeshes", inData, ownerPhysics);
++ }
++
++ template <typename TDataType>
++ void PvdMetaDataBinding::registrarPhysicsObject(PvdDataStream&, const TDataType&, PsPvd*)
++ {
++ }
++
++ template <>
++ void PvdMetaDataBinding::registrarPhysicsObject<PxConvexMeshGeometry>(PvdDataStream& inStream, const PxConvexMeshGeometry& geom, PsPvd* pvd)
++ {
++ if(pvd->registerObject(geom.convexMesh))
++ createInstance(inStream, *geom.convexMesh, PxGetPhysics());
++ }
++
++ template <>
++ void PvdMetaDataBinding::registrarPhysicsObject<PxTetrahedronMeshGeometry>(PvdDataStream& inStream, const PxTetrahedronMeshGeometry& geom, PsPvd* pvd)
++ {
++ if (pvd->registerObject(geom.tetrahedronMesh))
++ createInstance(inStream, *geom.tetrahedronMesh, PxGetPhysics());
++ }
++
++ template <>
++ void PvdMetaDataBinding::registrarPhysicsObject<PxTriangleMeshGeometry>(PvdDataStream& inStream, const PxTriangleMeshGeometry& geom, PsPvd* pvd)
++ {
++ if(pvd->registerObject(geom.triangleMesh))
++ createInstance(inStream, *geom.triangleMesh, PxGetPhysics());
++ }
++
++ template <>
++ void PvdMetaDataBinding::registrarPhysicsObject<PxHeightFieldGeometry>(PvdDataStream& inStream, const PxHeightFieldGeometry& geom, PsPvd* pvd)
++ {
++ if(pvd->registerObject(geom.heightField))
++ createInstance(inStream, *geom.heightField, PxGetPhysics());
++ }
++
++ template <typename TGeneratedValuesType, typename TGeomType>
++ static void sendGeometry(PvdMetaDataBinding& metaBind, PvdDataStream& inStream, const PxShape& inShape, const TGeomType& geom, PsPvd* pvd)
++ {
++ const void* geomInst = (reinterpret_cast<const PxU8*>(&inShape)) + 4;
++ inStream.createInstance(getPvdNamespacedNameForType<TGeomType>(), geomInst);
++ metaBind.registrarPhysicsObject<TGeomType>(inStream, geom, pvd);
++ TGeneratedValuesType values(&geom);
++ inStream.setPropertyMessage(geomInst, values);
++ inStream.setPropertyValue(&inShape, "Geometry", geomInst);
++ inStream.setPropertyValue(geomInst, "Shape", reinterpret_cast<const void*>(&inShape));
++ }
++
++ static void setGeometry(PvdMetaDataBinding& metaBind, PvdDataStream& inStream, const PxShape& inObj, PsPvd* pvd)
++ {
++ const PxGeometry& geom = inObj.getGeometry();
++ switch(geom.getType())
++ {
++ #define SEND_PVD_GEOM_TYPE(enumType, geomType, valueType) \
++ case PxGeometryType::enumType: \
++ { \
++ Px##geomType geomT = static_cast<const Px##geomType&>(geom); \
++ sendGeometry<valueType>(metaBind, inStream, inObj, geomT, pvd); \
++ } \
++ break;
++ SEND_PVD_GEOM_TYPE(eSPHERE, SphereGeometry, PxSphereGeometryGeneratedValues);
++ // Plane geometries don't have any properties, so this avoids using a property
++ // struct for them.
++ case PxGeometryType::ePLANE:
++ {
++ const void* geomInst = (reinterpret_cast<const PxU8*>(&inObj)) + 4;
++ inStream.createInstance(getPvdNamespacedNameForType<PxPlaneGeometry>(), geomInst);
++ inStream.setPropertyValue(&inObj, "Geometry", geomInst);
++ inStream.setPropertyValue(geomInst, "Shape", reinterpret_cast<const void*>(&inObj));
++ }
++ break;
++ SEND_PVD_GEOM_TYPE(eCAPSULE, CapsuleGeometry, PxCapsuleGeometryGeneratedValues);
++ SEND_PVD_GEOM_TYPE(eBOX, BoxGeometry, PxBoxGeometryGeneratedValues);
++ SEND_PVD_GEOM_TYPE(eCONVEXMESH, ConvexMeshGeometry, PxConvexMeshGeometryGeneratedValues);
++ SEND_PVD_GEOM_TYPE(eTETRAHEDRONMESH, TetrahedronMeshGeometry, PxTetrahedronMeshGeometryGeneratedValues);
++ SEND_PVD_GEOM_TYPE(eTRIANGLEMESH, TriangleMeshGeometry, PxTriangleMeshGeometryGeneratedValues);
++ SEND_PVD_GEOM_TYPE(eHEIGHTFIELD, HeightFieldGeometry, PxHeightFieldGeometryGeneratedValues);
++ SEND_PVD_GEOM_TYPE(eCUSTOM, CustomGeometry, PxCustomGeometryGeneratedValues);
++ #undef SEND_PVD_GEOM_TYPE
++ case PxGeometryType::eCONVEXCORE:
++ // VR implement later
++ break;
++ case PxGeometryType::ePARTICLESYSTEM:
++ // A.B. implement later
++ break;
++ case PxGeometryType::eGEOMETRY_COUNT:
++ case PxGeometryType::eINVALID:
++ PX_ASSERT(false);
++ break;
++ }
++ }
++
++ static void setMaterials(PvdMetaDataBinding& metaBing, PvdDataStream& inStream, const PxShape& inObj, PsPvd* pvd, PvdMetaDataBindingData* mBindingData)
++ {
++ PxU32 numMaterials = inObj.getNbMaterials();
++ PxMaterial** materialPtr = mBindingData->allocateTemp<PxMaterial*>(numMaterials);
++ inObj.getMaterials(materialPtr, numMaterials);
++ for(PxU32 idx = 0; idx < numMaterials; ++idx)
++ {
++ if(pvd->registerObject(materialPtr[idx]))
++ metaBing.createInstance(inStream, *materialPtr[idx], PxGetPhysics());
++ inStream.pushBackObjectRef(&inObj, "Materials", materialPtr[idx]);
++ }
++ }
++
++ void PvdMetaDataBinding::createInstance(PvdDataStream& inStream, const PxShape& inObj, const PxRigidActor& owner, const PxPhysics& ownerPhysics, PsPvd* pvd)
++ {
++ if(!inStream.isInstanceValid(&owner))
++ return;
++
++ const OwnerActorsMap::Entry* entry = mBindingData->mOwnerActorsMap.find(&inObj);
++ if(entry != NULL)
++ {
++ if(!mBindingData->mOwnerActorsMap[&inObj]->contains(&owner))
++ mBindingData->mOwnerActorsMap[&inObj]->insert(&owner);
++ }
++ else
++ {
++ OwnerActorsValueType* data = reinterpret_cast<OwnerActorsValueType*>(
++ PX_ALLOC(sizeof(OwnerActorsValueType), "mOwnerActorsMapValue")); //( 1 );
++ OwnerActorsValueType* actors = PX_PLACEMENT_NEW(data, OwnerActorsValueType);
++ actors->insert(&owner);
++
++ mBindingData->mOwnerActorsMap.insert(&inObj, actors);
++ }
++
++ if(inStream.isInstanceValid(&inObj))
++ {
++ inStream.pushBackObjectRef(&owner, "Shapes", &inObj);
++ return;
++ }
++
++ inStream.createInstance(&inObj);
++ inStream.pushBackObjectRef(&owner, "Shapes", &inObj);
++ inStream.setPropertyValue(&inObj, "Actor", reinterpret_cast<const void*>(&owner));
++ sendAllProperties(inStream, inObj);
++ setGeometry(*this, inStream, inObj, pvd);
++ setMaterials(*this, inStream, inObj, pvd, mBindingData);
++ if(!inObj.isExclusive())
++ inStream.pushBackObjectRef(&ownerPhysics, "SharedShapes", &inObj);
++ }
++
++ void PvdMetaDataBinding::sendAllProperties(PvdDataStream& inStream, const PxShape& inObj)
++ {
++ PxShapeGeneratedValues values(&inObj);
++ inStream.setPropertyMessage(&inObj, values);
++ }
++
++ void PvdMetaDataBinding::releaseAndRecreateGeometry(PvdDataStream& inStream, const PxShape& inObj, PxPhysics& /*ownerPhysics*/, PsPvd* pvd)
++ {
++ const void* geomInst = (reinterpret_cast<const PxU8*>(&inObj)) + 4;
++ inStream.destroyInstance(geomInst);
++ const PxGeometry& geom = inObj.getGeometry();
++ // Quick fix for HF modify, PxConvexMesh and PxTriangleMesh need recook, they should always be new if modified
++ if(geom.getType() == PxGeometryType::eHEIGHTFIELD)
++ {
++ const PxHeightFieldGeometry& hfGeom = static_cast<const PxHeightFieldGeometry&>(geom);
++ if(inStream.isInstanceValid(hfGeom.heightField))
++ sendAllProperties(inStream, *hfGeom.heightField);
++ }
++
++ setGeometry(*this, inStream, inObj, pvd);
++
++ // Need update actor cause PVD takes actor-shape as a pair.
++ {
++ PxRigidActor* actor = inObj.getActor();
++ if(actor != NULL)
++ {
++ if(const PxRigidStatic* rgS = actor->is<PxRigidStatic>())
++ sendAllProperties(inStream, *rgS);
++ else if(const PxRigidDynamic* rgD = actor->is<PxRigidDynamic>())
++ sendAllProperties(inStream, *rgD);
++ }
++ }
++ }
++
++ void PvdMetaDataBinding::updateMaterials(PvdDataStream& inStream, const PxShape& inObj, PsPvd* pvd)
++ {
++ // Clear the shape's materials array.
++ inStream.setPropertyValue(&inObj, "Materials", DataRef<const PxU8>(), getPvdNamespacedNameForType<ObjectRef>());
++ setMaterials(*this, inStream, inObj, pvd, mBindingData);
++ }
++
++ void PvdMetaDataBinding::destroyInstance(PvdDataStream& inStream, const PxShape& inObj, const PxRigidActor& owner)
++ {
++ if(inStream.isInstanceValid(&inObj))
++ {
++ inStream.removeObjectRef(&owner, "Shapes", &inObj);
++
++ bool bDestroy = true;
++ const OwnerActorsMap::Entry* entry0 = mBindingData->mOwnerActorsMap.find(&inObj);
++ if(entry0 != NULL)
++ {
++ entry0->second->erase(&owner);
++ if(entry0->second->size() > 0)
++ bDestroy = false;
++ else
++ {
++ mBindingData->mOwnerActorsMap[&inObj]->~OwnerActorsValueType();
++ PX_FREE(mBindingData->mOwnerActorsMap[&inObj]);
++ mBindingData->mOwnerActorsMap.erase(&inObj);
++ }
++ }
++
++ if(bDestroy)
++ {
++ if(!inObj.isExclusive())
++ inStream.removeObjectRef(&PxGetPhysics(), "SharedShapes", &inObj);
++
++ const void* geomInst = (reinterpret_cast<const PxU8*>(&inObj)) + 4;
++ inStream.destroyInstance(geomInst);
++ inStream.destroyInstance(&inObj);
++
++ const OwnerActorsMap::Entry* entry = mBindingData->mOwnerActorsMap.find(&inObj);
++ if(entry != NULL)
++ {
++ entry->second->~OwnerActorsValueType();
++ OwnerActorsValueType* ptr = entry->second;
++ PX_FREE(ptr);
++ mBindingData->mOwnerActorsMap.erase(&inObj);
++ }
++ }
++ }
++ }
++
++ template <typename TDataType>
++ static void addSceneGroupProperty(PvdDataStream& inStream, const char* groupName, const TDataType& inObj, const PxScene& inScene)
++ {
++ inStream.createInstance(&inObj);
++ inStream.pushBackObjectRef(&inScene, groupName, &inObj);
++ inStream.setPropertyValue(&inObj, "Scene", reinterpret_cast<const void*>(&inScene));
++ }
++
++ template <typename TDataType>
++ static void removeSceneGroupProperty(PvdDataStream& inStream, const char* groupName, const TDataType& inObj, const PxScene& inScene)
++ {
++ inStream.removeObjectRef(&inScene, groupName, &inObj);
++ inStream.destroyInstance(&inObj);
++ }
++
++ static void sendShapes(PvdMetaDataBinding& binding, PvdDataStream& inStream, const PxRigidActor& inObj, const PxPhysics& ownerPhysics, PsPvd* pvd)
++ {
++ PxInlineArray<PxShape*, 5> shapeData;
++ PxU32 nbShapes = inObj.getNbShapes();
++ shapeData.resize(nbShapes);
++ inObj.getShapes(shapeData.begin(), nbShapes);
++ for(PxU32 idx = 0; idx < nbShapes; ++idx)
++ binding.createInstance(inStream, *shapeData[idx], inObj, ownerPhysics, pvd);
++ }
++
++ static void releaseShapes(PvdMetaDataBinding& binding, PvdDataStream& inStream, const PxRigidActor& inObj)
++ {
++ PxInlineArray<PxShape*, 5> shapeData;
++ PxU32 nbShapes = inObj.getNbShapes();
++ shapeData.resize(nbShapes);
++ inObj.getShapes(shapeData.begin(), nbShapes);
++ for(PxU32 idx = 0; idx < nbShapes; ++idx)
++ binding.destroyInstance(inStream, *shapeData[idx], inObj);
++ }
++
++ void PvdMetaDataBinding::createInstance(PvdDataStream& inStream, const PxRigidStatic& inObj, const PxScene& ownerScene, const PxPhysics& ownerPhysics, PsPvd* pvd)
++ {
++ addSceneGroupProperty(inStream, "RigidStatics", inObj, ownerScene);
++ sendAllProperties(inStream, inObj);
++ sendShapes(*this, inStream, inObj, ownerPhysics, pvd);
++ }
++ void PvdMetaDataBinding::sendAllProperties(PvdDataStream& inStream, const PxRigidStatic& inObj)
++ {
++ PxRigidStaticGeneratedValues values(&inObj);
++ inStream.setPropertyMessage(&inObj, values);
++ }
++ void PvdMetaDataBinding::destroyInstance(PvdDataStream& inStream, const PxRigidStatic& inObj, const PxScene& ownerScene)
++ {
++ releaseShapes(*this, inStream, inObj);
++ removeSceneGroupProperty(inStream, "RigidStatics", inObj, ownerScene);
++ }
++ void PvdMetaDataBinding::createInstance(PvdDataStream& inStream, const PxRigidDynamic& inObj, const PxScene& ownerScene, const PxPhysics& ownerPhysics, PsPvd* pvd)
++ {
++ addSceneGroupProperty(inStream, "RigidDynamics", inObj, ownerScene);
++ sendAllProperties(inStream, inObj);
++ sendShapes(*this, inStream, inObj, ownerPhysics, pvd);
++ }
++ void PvdMetaDataBinding::sendAllProperties(PvdDataStream& inStream, const PxRigidDynamic& inObj)
++ {
++ PxRigidDynamicGeneratedValues values(&inObj);
++ inStream.setPropertyMessage(&inObj, values);
++ }
++ void PvdMetaDataBinding::destroyInstance(PvdDataStream& inStream, const PxRigidDynamic& inObj, const PxScene& ownerScene)
++ {
++ releaseShapes(*this, inStream, inObj);
++ removeSceneGroupProperty(inStream, "RigidDynamics", inObj, ownerScene);
++ }
++
++ static void addChild(PvdDataStream& inStream, const void* inParent, const PxArticulationLink& inChild)
++ {
++ inStream.pushBackObjectRef(inParent, "Links", &inChild);
++ inStream.setPropertyValue(&inChild, "Parent", inParent);
++ }
++
++ void PvdMetaDataBinding::createInstance(PvdDataStream& inStream, const PxArticulationReducedCoordinate& inObj, const PxScene& ownerScene, const PxPhysics& ownerPhysics, PsPvd* pvd)
++ {
++ addSceneGroupProperty(inStream, "Articulations", inObj, ownerScene);
++ sendAllProperties(inStream, inObj);
++ PxU32 numLinks = inObj.getNbLinks();
++ mBindingData->mArticulationLinks.resize(numLinks);
++ inObj.getLinks(mBindingData->mArticulationLinks.begin(), numLinks);
++ // From Dilip Sequiera:
++ /*
++ No, there can only be one root, and in all the code I wrote (which is not 100% of the HL code for
++ articulations), the index of a child is always > the index of the parent.
++ */
++
++ // Create all the links
++ for(PxU32 idx = 0; idx < numLinks; ++idx)
++ {
++ if(!inStream.isInstanceValid(mBindingData->mArticulationLinks[idx]))
++ createInstance(inStream, *mBindingData->mArticulationLinks[idx], ownerPhysics, pvd);
++ }
++
++ // Setup the link graph
++ for(PxU32 idx = 0; idx < numLinks; ++idx)
++ {
++ PxArticulationLink* link = mBindingData->mArticulationLinks[idx];
++ if(idx == 0)
++ addChild(inStream, &inObj, *link);
++
++ PxU32 numChildren = link->getNbChildren();
++ PxArticulationLink** children = mBindingData->allocateTemp<PxArticulationLink*>(numChildren);
++ link->getChildren(children, numChildren);
++ for(PxU32 i = 0; i < numChildren; ++i)
++ addChild(inStream, link, *children[i]);
++ }
++ }
++
++ void PvdMetaDataBinding::sendAllProperties(PvdDataStream& inStream, const PxArticulationReducedCoordinate& inObj)
++ {
++ PxArticulationReducedCoordinateGeneratedValues values(&inObj);
++ inStream.setPropertyMessage(&inObj, values);
++ }
++
++ void PvdMetaDataBinding::destroyInstance(PvdDataStream& inStream, const PxArticulationReducedCoordinate& inObj, const PxScene& ownerScene)
++ {
++ removeSceneGroupProperty(inStream, "Articulations", inObj, ownerScene);
++ }
++
++ void PvdMetaDataBinding::createInstance(PvdDataStream& inStream, const PxArticulationLink& inObj, const PxPhysics& ownerPhysics, PsPvd* pvd)
++ {
++ inStream.createInstance(&inObj);
++ PxArticulationJointReducedCoordinate* joint(inObj.getInboundJoint());
++ if(joint)
++ {
++ inStream.createInstance(joint);
++ inStream.setPropertyValue(&inObj, "InboundJoint", reinterpret_cast<const void*>(joint));
++ inStream.setPropertyValue(joint, "Link", reinterpret_cast<const void*>(&inObj));
++ sendAllProperties(inStream, *joint);
++ }
++ sendAllProperties(inStream, inObj);
++ sendShapes(*this, inStream, inObj, ownerPhysics, pvd);
++ }
++
++ void PvdMetaDataBinding::sendAllProperties(PvdDataStream& inStream, const PxArticulationLink& inObj)
++ {
++ PxArticulationLinkGeneratedValues values(&inObj);
++ inStream.setPropertyMessage(&inObj, values);
++ }
++
++ void PvdMetaDataBinding::destroyInstance(PvdDataStream& inStream, const PxArticulationLink& inObj)
++ {
++ PxArticulationJointReducedCoordinate* joint(inObj.getInboundJoint());
++ if(joint)
++ inStream.destroyInstance(joint);
++ releaseShapes(*this, inStream, inObj);
++ inStream.destroyInstance(&inObj);
++ }
++ // These are created as part of the articulation link's creation process, so outside entities don't need to
++ // create them.
++ void PvdMetaDataBinding::sendAllProperties(PvdDataStream& inStream, const PxArticulationJointReducedCoordinate& inObj)
++ {
++ PxArticulationJointReducedCoordinateGeneratedValues values(&inObj);
++ inStream.setPropertyMessage(&inObj, values);
++ }
++
++ void PvdMetaDataBinding::createInstance(PvdDataStream& inStream, const PxDeformableVolume& inObj, const PxScene& ownerScene, const PxPhysics& ownerPhysics, PsPvd* pvd)
++ {
++ PX_UNUSED(inStream);
++ PX_UNUSED(inObj);
++ PX_UNUSED(ownerScene);
++ PX_UNUSED(ownerPhysics);
++ PX_UNUSED(pvd);
++ }
++
++ void PvdMetaDataBinding::sendAllProperties(PvdDataStream& inStream, const PxDeformableVolume& inObj)
++ {
++ PX_UNUSED(inStream);
++ PX_UNUSED(inObj);
++ }
++
++ void PvdMetaDataBinding::destroyInstance(PvdDataStream& inStream, const PxDeformableVolume& inObj, const PxScene& ownerScene)
++ {
++ PX_UNUSED(inStream);
++ PX_UNUSED(inObj);
++ PX_UNUSED(ownerScene);
++ }
++
++ void PvdMetaDataBinding::createInstance(PvdDataStream& inStream, const PxDeformableSurface& inObj, const PxScene& ownerScene, const PxPhysics& ownerPhysics, PsPvd* pvd)
++ {
++ PX_UNUSED(inStream);
++ PX_UNUSED(inObj);
++ PX_UNUSED(ownerScene);
++ PX_UNUSED(ownerPhysics);
++ PX_UNUSED(pvd);
++ }
++
++ void PvdMetaDataBinding::sendAllProperties(PvdDataStream& inStream, const PxDeformableSurface& inObj)
++ {
++ PX_UNUSED(inStream);
++ PX_UNUSED(inObj);
++ }
++
++ void PvdMetaDataBinding::destroyInstance(PvdDataStream& inStream, const PxDeformableSurface& inObj, const PxScene& ownerScene)
++ {
++ PX_UNUSED(inStream);
++ PX_UNUSED(inObj);
++ PX_UNUSED(ownerScene);
++ }
++
++ void PvdMetaDataBinding::createInstance(PvdDataStream& inStream, const PxPBDParticleSystem& inObj, const PxScene& ownerScene, const PxPhysics& ownerPhysics, PsPvd* pvd)
++ {
++ PX_UNUSED(inStream);
++ PX_UNUSED(inObj);
++ PX_UNUSED(ownerScene);
++ PX_UNUSED(ownerPhysics);
++ PX_UNUSED(pvd);
++ }
++
++ void PvdMetaDataBinding::sendAllProperties(PvdDataStream& inStream, const PxPBDParticleSystem& inObj)
++ {
++ PX_UNUSED(inStream);
++ PX_UNUSED(inObj);
++ }
++
++ void PvdMetaDataBinding::destroyInstance(PvdDataStream& inStream, const PxPBDParticleSystem& inObj, const PxScene& ownerScene)
++ {
++ PX_UNUSED(inStream);
++ PX_UNUSED(inObj);
++ PX_UNUSED(ownerScene);
++ }
++
++ void PvdMetaDataBinding::originShift(PvdDataStream& inStream, const PxScene* inScene, PxVec3 shift)
++ {
++ inStream.originShift(inScene, shift);
++ }
++
++ template <typename TBlockType, typename TActorType, typename TOperator>
++ static void updateActor(PvdDataStream& inStream, TActorType** actorGroup, PxU32 numActors, TOperator sleepingOp, PvdMetaDataBindingData& bindingData)
++ {
++ TBlockType theBlock;
++ if(numActors == 0)
++ return;
++ for(PxU32 idx = 0; idx < numActors; ++idx)
++ {
++ TActorType* theActor(actorGroup[idx]);
++ bool sleeping = sleepingOp(theActor, theBlock);
++ bool wasSleeping = bindingData.mSleepingActors.contains(theActor);
++
++ if(sleeping == false || sleeping != wasSleeping)
++ {
++ theBlock.GlobalPose = theActor->getGlobalPose();
++ theBlock.AngularVelocity = theActor->getAngularVelocity();
++ theBlock.LinearVelocity = theActor->getLinearVelocity();
++ inStream.sendPropertyMessageFromGroup(theActor, theBlock);
++ if(sleeping != wasSleeping)
++ {
++ if(sleeping)
++ bindingData.mSleepingActors.insert(theActor);
++ else
++ bindingData.mSleepingActors.erase(theActor);
++ }
++ }
++ }
++ }
++
++ struct RigidDynamicUpdateOp
++ {
++ bool operator()(PxRigidDynamic* actor, PxRigidDynamicUpdateBlock& block)
++ {
++ bool sleeping = actor->isSleeping();
++ block.IsSleeping = sleeping;
++ return sleeping;
++ }
++ };
++
++ struct ArticulationLinkUpdateOp
++ {
++ bool sleeping;
++ ArticulationLinkUpdateOp(bool s) : sleeping(s)
++ {
++ }
++ bool operator()(PxArticulationLink*, PxArticulationLinkUpdateBlock&)
++ {
++ return sleeping;
++ }
++ };
++
++ void PvdMetaDataBinding::updateDynamicActorsAndArticulations(PvdDataStream& inStream, const PxScene* inScene, PvdVisualizer* linkJointViz)
++ {
++ PX_COMPILE_TIME_ASSERT(sizeof(PxRigidDynamicUpdateBlock) == 14 * 4);
++ {
++ PxU32 actorCount = inScene->getNbActors(PxActorTypeFlag::eRIGID_DYNAMIC);
++ if(actorCount)
++ {
++ inStream.beginPropertyMessageGroup<PxRigidDynamicUpdateBlock>();
++ mBindingData->mActors.resize(actorCount);
++ PxActor** theActors = mBindingData->mActors.begin();
++ inScene->getActors(PxActorTypeFlag::eRIGID_DYNAMIC, theActors, actorCount);
++ updateActor<PxRigidDynamicUpdateBlock>(inStream, reinterpret_cast<PxRigidDynamic**>(theActors), actorCount, RigidDynamicUpdateOp(), *mBindingData);
++ inStream.endPropertyMessageGroup();
++ }
++ }
++ {
++ PxU32 articulationCount = inScene->getNbArticulations();
++ if(articulationCount)
++ {
++ mBindingData->mArticulations.resize(articulationCount);
++ PxArticulationReducedCoordinate** firstArticulation = mBindingData->mArticulations.begin();
++ PxArticulationReducedCoordinate** lastArticulation = firstArticulation + articulationCount;
++ inScene->getArticulations(firstArticulation, articulationCount);
++ inStream.beginPropertyMessageGroup<PxArticulationLinkUpdateBlock>();
++ for(; firstArticulation < lastArticulation; ++firstArticulation)
++ {
++ PxU32 linkCount = (*firstArticulation)->getNbLinks();
++ bool sleeping = (*firstArticulation)->isSleeping();
++ if(linkCount)
++ {
++ mBindingData->mArticulationLinks.resize(linkCount);
++ PxArticulationLink** theLink = mBindingData->mArticulationLinks.begin();
++ (*firstArticulation)->getLinks(theLink, linkCount);
++ updateActor<PxArticulationLinkUpdateBlock>(inStream, theLink, linkCount, ArticulationLinkUpdateOp(sleeping), *mBindingData);
++ if(linkJointViz)
++ {
++ for(PxU32 idx = 0; idx < linkCount; ++idx)
++ linkJointViz->visualize(*theLink[idx]);
++ }
++ }
++ }
++ inStream.endPropertyMessageGroup();
++ firstArticulation = mBindingData->mArticulations.begin();
++ for (; firstArticulation < lastArticulation; ++firstArticulation)
++ {
++ inStream.setPropertyValue(*firstArticulation, "IsSleeping", (*firstArticulation)->isSleeping());
++ inStream.setPropertyValue(*firstArticulation, "RootGlobalPose", (*firstArticulation)->getRootGlobalPose());
++ inStream.setPropertyValue(*firstArticulation, "RootLinearVelocity", (*firstArticulation)->getRootLinearVelocity());
++ inStream.setPropertyValue(*firstArticulation, "RootAngularVelocity", (*firstArticulation)->getRootAngularVelocity());
++ }
++
++ inStream.beginPropertyMessageGroup<PxArticulationJointUpdateBlock>();
++ firstArticulation = mBindingData->mArticulations.begin();
++
++ for (; firstArticulation < lastArticulation; ++firstArticulation)
++ {
++ PxU32 linkCount = (*firstArticulation)->getNbLinks();
++ bool sleeping = (*firstArticulation)->isSleeping();
++ if (!sleeping)
++ {
++ for (PxU32 idx = 1; idx < linkCount; ++idx)
++ {
++ mBindingData->mArticulationLinks.resize(linkCount);
++ PxArticulationLink** theLink = mBindingData->mArticulationLinks.begin();
++ (*firstArticulation)->getLinks(theLink, linkCount);
++
++ PxArticulationJointUpdateBlock jointBlock;
++ PxArticulationJointReducedCoordinate* joint = theLink[idx]->getInboundJoint();
++ jointBlock.JointPosition_eX = joint->getJointPosition(PxArticulationAxis::eX);
++ jointBlock.JointPosition_eY = joint->getJointPosition(PxArticulationAxis::eY);
++ jointBlock.JointPosition_eZ = joint->getJointPosition(PxArticulationAxis::eZ);
++ jointBlock.JointPosition_eTwist = joint->getJointPosition(PxArticulationAxis::eTWIST);
++ jointBlock.JointPosition_eSwing1 = joint->getJointPosition(PxArticulationAxis::eSWING1);
++ jointBlock.JointPosition_eSwing2 = joint->getJointPosition(PxArticulationAxis::eSWING2);
++
++ jointBlock.JointVelocity_eX = joint->getJointVelocity(PxArticulationAxis::eX);
++ jointBlock.JointVelocity_eY = joint->getJointVelocity(PxArticulationAxis::eY);
++ jointBlock.JointVelocity_eZ = joint->getJointVelocity(PxArticulationAxis::eZ);
++ jointBlock.JointVelocity_eTwist = joint->getJointVelocity(PxArticulationAxis::eTWIST);
++ jointBlock.JointVelocity_eSwing1 = joint->getJointVelocity(PxArticulationAxis::eSWING1);
++ jointBlock.JointVelocity_eSwing2 = joint->getJointVelocity(PxArticulationAxis::eSWING2);
++
++ inStream.sendPropertyMessageFromGroup(joint, jointBlock);
++ }
++ }
++ }
++ inStream.endPropertyMessageGroup();
++ }
++ }
++ }
++
++ template <typename TObjType>
++ struct CollectionOperator
++ {
++ PxArray<PxU8>& mTempArray;
++ const TObjType& mObject;
++ PvdDataStream& mStream;
++
++ CollectionOperator(PxArray<PxU8>& ary, const TObjType& obj, PvdDataStream& stream)
++ : mTempArray(ary), mObject(obj), mStream(stream)
++ {
++ }
++ void pushName(const char*)
++ {
++ }
++ void popName()
++ {
++ }
++ template <typename TAccessor>
++ void simpleProperty(PxU32 /*key*/, const TAccessor&)
++ {
++ }
++ template <typename TAccessor>
++ void flagsProperty(PxU32 /*key*/, const TAccessor&, const PxU32ToName*)
++ {
++ }
++
++ template <typename TColType, typename TDataType, typename TCollectionProp>
++ void handleCollection(const TCollectionProp& prop, NamespacedName dtype, PxU32 countMultiplier = 1)
++ {
++ PxU32 count = prop.size(&mObject);
++ mTempArray.resize(count * sizeof(TDataType));
++ TColType* start = reinterpret_cast<TColType*>(mTempArray.begin());
++ prop.get(&mObject, start, count * countMultiplier);
++ mStream.setPropertyValue(&mObject, prop.mName, DataRef<const PxU8>(mTempArray.begin(), mTempArray.size()), dtype);
++ }
++ template <PxU32 TKey, typename TObject, typename TColType>
++ void handleCollection(const PxReadOnlyCollectionPropertyInfo<TKey, TObject, TColType>& prop)
++ {
++ handleCollection<TColType, TColType>(prop, getPvdNamespacedNameForType<TColType>());
++ }
++ // Enumerations or bitflags.
++ template <PxU32 TKey, typename TObject, typename TColType>
++ void handleCollection(const PxReadOnlyCollectionPropertyInfo<TKey, TObject, TColType>& prop, const PxU32ToName*)
++ {
++ PX_COMPILE_TIME_ASSERT(sizeof(TColType) == sizeof(PxU32));
++ handleCollection<TColType, PxU32>(prop, getPvdNamespacedNameForType<PxU32>());
++ }
++
++ private:
++ CollectionOperator& operator=(const CollectionOperator&);
++ };
++
++ // per frame update
++
++ #define ENABLE_AGGREGATE_PVD_SUPPORT 1
++ #ifdef ENABLE_AGGREGATE_PVD_SUPPORT
++
++ void PvdMetaDataBinding::createInstance(PvdDataStream& inStream, const PxAggregate& inObj, const PxScene& ownerScene)
++ {
++ addSceneGroupProperty(inStream, "Aggregates", inObj, ownerScene);
++ sendAllProperties(inStream, inObj);
++ }
++
++ void PvdMetaDataBinding::sendAllProperties(PvdDataStream& inStream, const PxAggregate& inObj)
++ {
++ PxAggregateGeneratedValues values(&inObj);
++ inStream.setPropertyMessage(&inObj, values);
++ }
++
++ void PvdMetaDataBinding::destroyInstance(PvdDataStream& inStream, const PxAggregate& inObj, const PxScene& ownerScene)
++ {
++ removeSceneGroupProperty(inStream, "Aggregates", inObj, ownerScene);
++ }
++
++ class ChangeOjectRefCmd : public PvdDataStream::PvdCommand
++ {
++ ChangeOjectRefCmd& operator=(const ChangeOjectRefCmd&)
++ {
++ PX_ASSERT(0);
++ return *this;
++ } // PX_NOCOPY doesn't work for local classes
++ public:
++ const void* mInstance;
++ String mPropName;
++ const void* mPropObj;
++ const bool mPushBack;
++
++ ChangeOjectRefCmd(const void* inInst, String inName, const void* inObj, bool pushBack)
++ : mInstance(inInst), mPropName(inName), mPropObj(inObj), mPushBack(pushBack)
++ {
++ }
++
++ // Assigned is needed for copying
++ ChangeOjectRefCmd(const ChangeOjectRefCmd& other)
++ : PvdDataStream::PvdCommand(other), mInstance(other.mInstance), mPropName(other.mPropName), mPropObj(other.mPropObj), mPushBack(other.mPushBack)
++ {
++ }
++
++ virtual bool canRun(PvdInstanceDataStream& inStream) PX_OVERRIDE
++ {
++ PX_ASSERT(inStream.isInstanceValid(mInstance));
++ return inStream.isInstanceValid(mPropObj);
++ }
++ virtual void run(PvdInstanceDataStream& inStream) PX_OVERRIDE
++ {
++ if(!inStream.isInstanceValid(mInstance))
++ return;
++
++ if(mPushBack)
++ {
++ if(inStream.isInstanceValid(mPropObj))
++ inStream.pushBackObjectRef(mInstance, mPropName, mPropObj);
++ }
++ else
++ {
++ // the called function will assert if propobj is already removed
++ inStream.removeObjectRef(mInstance, mPropName, mPropObj);
++ }
++ }
++ };
++
++ static void changeAggregateSubActors(PvdDataStream& inStream, const PxAggregate& inObj, const PxActor& inActor, bool pushBack)
++ {
++ const PxArticulationLink* link = inActor.is<PxArticulationLink>();
++ String propName = NULL;
++ const void* object = NULL;
++ if(link == NULL)
++ {
++ propName = "Actors";
++ object = &inActor;
++ }
++ else if(link->getInboundJoint() == NULL)
++ {
++ propName = "Articulations";
++ object = &link->getArticulation();
++ }
++ else
++ return;
++
++ ChangeOjectRefCmd* cmd = PX_PLACEMENT_NEW(inStream.allocateMemForCmd(sizeof(ChangeOjectRefCmd)), ChangeOjectRefCmd)(&inObj, propName, object, pushBack);
++
++ if(cmd->canRun(inStream))
++ cmd->run(inStream);
++ else
++ inStream.pushPvdCommand(*cmd);
++ }
++ void PvdMetaDataBinding::detachAggregateActor(PvdDataStream& inStream, const PxAggregate& inObj, const PxActor& inActor)
++ {
++ changeAggregateSubActors(inStream, inObj, inActor, false);
++ }
++
++ void PvdMetaDataBinding::attachAggregateActor(PvdDataStream& inStream, const PxAggregate& inObj, const PxActor& inActor)
++ {
++ changeAggregateSubActors(inStream, inObj, inActor, true);
++ }
++ #else
++ void PvdMetaDataBinding::createInstance(PvdDataStream&, const PxAggregate&, const PxScene&, ObjectRegistrar&)
++ {
++ }
++
++ void PvdMetaDataBinding::sendAllProperties(PvdDataStream&, const PxAggregate&)
++ {
++ }
++
++ void PvdMetaDataBinding::destroyInstance(PvdDataStream&, const PxAggregate&, const PxScene&)
++ {
++ }
++
++ void PvdMetaDataBinding::detachAggregateActor(PvdDataStream&, const PxAggregate&, const PxActor&)
++ {
++ }
++
++ void PvdMetaDataBinding::attachAggregateActor(PvdDataStream&, const PxAggregate&, const PxActor&)
++ {
++ }
++ #endif
++
++ template <typename TDataType>
++ static void sendSceneArray(PvdDataStream& inStream, const PxScene& inScene, const PxArray<TDataType>& inArray, const char* propName)
++ {
++ if(0 == inArray.size())
++ inStream.setPropertyValue(&inScene, propName, DataRef<const PxU8>(), getPvdNamespacedNameForType<TDataType>());
++ else
++ {
++ ScopedPropertyValueSender<TDataType, 32> sender(inStream, &inScene, propName);
++ for(PxU32 i = 0; i < inArray.size(); ++i)
++ sender.append(inArray[i]);
++ }
++ }
++
++ static void sendSceneArray(PvdDataStream& inStream, const PxScene& inScene, const PxArray<PvdSqHit>& inArray, const char* propName)
++ {
++ if(0 == inArray.size())
++ inStream.setPropertyValue(&inScene, propName, DataRef<const PxU8>(), getPvdNamespacedNameForType<PvdSqHit>());
++ else
++ {
++ ScopedPropertyValueSender<PvdSqHit, 32> sender(inStream, &inScene, propName);
++ for(PxU32 i = 0; i < inArray.size(); ++i)
++ {
++ if(!inStream.isInstanceValid(inArray[i].mShape) || !inStream.isInstanceValid(inArray[i].mActor))
++ {
++ PvdSqHit hit = inArray[i];
++ hit.mShape = NULL;
++ hit.mActor = NULL;
++ sender.append(hit);
++ }
++ else
++ sender.append(inArray[i]);
++ }
++ }
++ }
++
++ void PvdMetaDataBinding::sendSceneQueries(PvdDataStream& inStream, const PxScene& inScene, PsPvd* pvd)
++ {
++ if(!inStream.isConnected())
++ return;
++
++ const physx::NpScene& scene = static_cast<const NpScene&>(inScene);
++
++ {
++ PvdSceneQueryCollector& collector = scene.getNpSQ().getSingleSqCollector();
++ PxMutex::ScopedLock lock(collector.getLock());
++
++ String propName = collector.getArrayName(collector.mPvdSqHits);
++ sendSceneArray(inStream, inScene, collector.mPvdSqHits, propName);
++
++ propName = collector.getArrayName(collector.mPoses);
++ sendSceneArray(inStream, inScene, collector.mPoses, propName);
++
++ propName = collector.getArrayName(collector.mFilterData);
++ sendSceneArray(inStream, inScene, collector.mFilterData, propName);
++
++ const NamedArray<PxGeometryHolder>& geometriesToDestroy = collector.getPrevFrameGeometries();
++ propName = collector.getArrayName(geometriesToDestroy);
++ for(PxU32 k = 0; k < geometriesToDestroy.size(); ++k)
++ {
++ const PxGeometryHolder& inObj = geometriesToDestroy[k];
++ inStream.removeObjectRef(&inScene, propName, &inObj);
++ inStream.destroyInstance(&inObj);
++ }
++ const PxArray<PxGeometryHolder>& geometriesToCreate = collector.getCurrentFrameGeometries();
++ for(PxU32 k = 0; k < geometriesToCreate.size(); ++k)
++ {
++ const PxGeometry& geometry = geometriesToCreate[k].any();
++ switch(geometry.getType())
++ {
++ #define SEND_PVD_GEOM_TYPE(enumType, TGeomType, TValueType) \
++ case enumType: \
++ { \
++ const TGeomType& inObj = static_cast<const TGeomType&>(geometry); \
++ inStream.createInstance(getPvdNamespacedNameForType<TGeomType>(), &inObj); \
++ registrarPhysicsObject<TGeomType>(inStream, inObj, pvd); \
++ TValueType values(&inObj); \
++ inStream.setPropertyMessage(&inObj, values); \
++ inStream.pushBackObjectRef(&inScene, propName, &inObj); \
++ } \
++ break;
++ SEND_PVD_GEOM_TYPE(PxGeometryType::eBOX, PxBoxGeometry, PxBoxGeometryGeneratedValues)
++ SEND_PVD_GEOM_TYPE(PxGeometryType::eSPHERE, PxSphereGeometry, PxSphereGeometryGeneratedValues)
++ SEND_PVD_GEOM_TYPE(PxGeometryType::eCAPSULE, PxCapsuleGeometry, PxCapsuleGeometryGeneratedValues)
++ SEND_PVD_GEOM_TYPE(PxGeometryType::eCONVEXMESH, PxConvexMeshGeometry, PxConvexMeshGeometryGeneratedValues)
++ #undef SEND_PVD_GEOM_TYPE
++ case PxGeometryType::ePLANE:
++ case PxGeometryType::eTRIANGLEMESH:
++ case PxGeometryType::eHEIGHTFIELD:
++ case PxGeometryType::eTETRAHEDRONMESH:
++ case PxGeometryType::ePARTICLESYSTEM:
++ case PxGeometryType::eCONVEXCORE:
++ case PxGeometryType::eCUSTOM:
++ case PxGeometryType::eGEOMETRY_COUNT:
++ case PxGeometryType::eINVALID:
++ PX_ALWAYS_ASSERT_MESSAGE("unsupported scene query geometry type");
++ break;
++ }
++ }
++ collector.prepareNextFrameGeometries();
++
++ propName = collector.getArrayName(collector.mAccumulatedRaycastQueries);
++ sendSceneArray(inStream, inScene, collector.mAccumulatedRaycastQueries, propName);
++
++ propName = collector.getArrayName(collector.mAccumulatedOverlapQueries);
++ sendSceneArray(inStream, inScene, collector.mAccumulatedOverlapQueries, propName);
++
++ propName = collector.getArrayName(collector.mAccumulatedSweepQueries);
++ sendSceneArray(inStream, inScene, collector.mAccumulatedSweepQueries, propName);
++ }
++ }
++ }
++ }
++
++ #endif