void PhysXHeightfield::InitHeightfield(PxPhysics* physics, PxScene* scene, const char* filename) { float xScale = 0.0025f; float yScale = 0.0025f; float zScale = 10.00f; // NOTE: Assuming that heightfield texture has B8G8R8A8 format. if(LoadHeightfield(filename)) { PxU16 nbColumns = PxU16(mHeightfield.width); PxU16 nbRows = PxU16(mHeightfield.height); PxHeightFieldDesc heightFieldDesc; heightFieldDesc.format = PxHeightFieldFormat::eS16_TM; heightFieldDesc.nbColumns = nbColumns; heightFieldDesc.nbRows = nbRows; heightFieldDesc.samples.data = mHeightfield.data; heightFieldDesc.samples.stride = sizeof(PxHeightFieldSample); //heightFieldDesc.convexEdgeThreshold = 0; PxHeightField* heightField = physics->createHeightField(heightFieldDesc); // create shape for heightfield PxTransform pose(PxVec3(-((PxReal)nbRows*yScale) / 2.0f, 0.0f, -((PxReal)nbColumns*xScale) / 2.0f), PxQuat::createIdentity()); // PxTransform pose = PxTransform::createIdentity(); pose.p = PxVec3(-((nbColumns/2)*xScale),0.0,-((nbColumns/2)*xScale)); PxRigidActor* hf = physics->createRigidStatic(pose); if(!hf) return; const PxMaterial* mMat = physics->createMaterial(0.9f, 0.9f, 0.001f); //PxShape* shape = hf->createShape((PxHeightFieldGeometry(heightField, PxMeshGeometryFlags(), yScale, xScale, xScale)), *mMat); //PxHeightFieldGeometry hfGeom(heightField, PxMeshGeometryFlags(), heightScale, rowScale, colScale); //PxShape* aHeightFieldShape = aHeightFieldActor->createShape(hfGeom, aMaterialArray, nbMaterials); PxHeightFieldGeometry hfGeom(heightField, PxMeshGeometryFlags(), yScale, xScale, xScale); PxShape* hfShape = hf->createShape(hfGeom, *mMat); if(!hfShape) return; //shape->setFlag(PxShapeFlag::ePARTICLE_DRAIN, false); //shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, true); //shape->setFlag(PxShapeFlag::eUSE_SWEPT_BOUNDS, true); // add actor to the scene scene->addActor(*hf); } }
bool setupFinalizeExtSolverConstraintsCoulomb(PxcNpWorkUnit& n, const ContactBuffer& buffer, const PxcCorrelationBufferCoulomb& c, const PxTransform& bodyFrame0, const PxTransform& bodyFrame1, bool /*perPointFriction*/, PxU8* workspace, PxReal invDt, PxReal bounceThreshold, PxsSolverExtBody& b0, PxsSolverExtBody& b1, PxU32 frictionCountPerPoint, PxReal invMassScale0, PxReal invInertiaScale0, PxReal invMassScale1, PxReal invInertiaScale1) { // NOTE II: the friction patches are sparse (some of them have no contact patches, and // therefore did not get written back to the cache) but the patch addresses are dense, // corresponding to valid patches PxU8* PX_RESTRICT ptr = workspace; const FloatV zero=FZero(); //KS - TODO - this should all be done in SIMD to avoid LHS const PxF32 maxPenBias0 = b0.mLinkIndex == PxcSolverConstraintDesc::NO_LINK ? b0.mBodyData->penBiasClamp : getMaxPenBias(*b0.mFsData)[b0.mLinkIndex]; const PxF32 maxPenBias1 = b1.mLinkIndex == PxcSolverConstraintDesc::NO_LINK ? b1.mBodyData->penBiasClamp : getMaxPenBias(*b1.mFsData)[b0.mLinkIndex]; const FloatV maxPen = FLoad(PxMax(maxPenBias0, maxPenBias1)/invDt); const FloatV restDistance = FLoad(n.restDistance); Ps::prefetchLine(c.contactID); Ps::prefetchLine(c.contactID, 128); bool useExtContacts = (n.flags & (PxcNpWorkUnitFlag::eARTICULATION_BODY0|PxcNpWorkUnitFlag::eARTICULATION_BODY1))!=0; const PxU32 frictionPatchCount = c.frictionPatchCount; const bool staticBody = ((n.flags & PxcNpWorkUnitFlag::eDYNAMIC_BODY1) == 0); const PxU32 pointStride = useExtContacts ? sizeof(PxcSolverContactExt) : sizeof(PxcSolverContact); const PxU32 frictionStride = useExtContacts ? sizeof(PxcSolverFrictionExt) : sizeof(PxcSolverFriction); const PxU8 pointHeaderType = Ps::to8(useExtContacts ? PXS_SC_TYPE_EXT_CONTACT : (staticBody ? PXS_SC_TYPE_STATIC_CONTACT : PXS_SC_TYPE_RB_CONTACT)); const PxU8 frictionHeaderType = Ps::to8(useExtContacts ? PXS_SC_TYPE_EXT_FRICTION : (staticBody ? PXS_SC_TYPE_STATIC_FRICTION : PXS_SC_TYPE_FRICTION)); PxReal d0 = n.dominance0 * invMassScale0; PxReal d1 = n.dominance1 * invMassScale1; PxReal angD0 = n.dominance0 * invInertiaScale0; PxReal angD1 = n.dominance1 * invInertiaScale1; for(PxU32 i=0;i< frictionPatchCount;i++) { const PxU32 contactCount = c.frictionPatchContactCounts[i]; if(contactCount == 0) continue; const Gu::ContactPoint* contactBase0 = buffer.contacts + c.contactPatches[c.correlationListHeads[i]].start; const PxcFrictionPatchCoulomb& frictionPatch = c.frictionPatches[i]; const Vec3V normalV = Ps::aos::V3LoadU(frictionPatch.normal); const PxVec3 normal = frictionPatch.normal; const PxReal combinedRestitution = contactBase0->restitution; PxcSolverContactCoulombHeader* PX_RESTRICT header = reinterpret_cast<PxcSolverContactCoulombHeader*>(ptr); ptr += sizeof(PxcSolverContactCoulombHeader); Ps::prefetchLine(ptr, 128); Ps::prefetchLine(ptr, 256); Ps::prefetchLine(ptr, 384); header->numNormalConstr = (PxU8)contactCount; header->type = pointHeaderType; header->setRestitution(combinedRestitution); header->setDominance0(d0); header->setDominance1(d1); header->angDom0 = angD0; header->angDom1 = angD1; header->setNormal(normalV); for(PxU32 patch=c.correlationListHeads[i]; patch!=PxcCorrelationBuffer::LIST_END; patch = c.contactPatches[patch].next) { const PxU32 count = c.contactPatches[patch].count; const Gu::ContactPoint* contactBase = buffer.contacts + c.contactPatches[patch].start; PxU8* p = ptr; for(PxU32 j=0;j<count;j++) { const Gu::ContactPoint& contact = contactBase[j]; PxcSolverContactExt* PX_RESTRICT solverContact = reinterpret_cast<PxcSolverContactExt*>(p); p += pointStride; const FloatV separation = FLoad(contact.separation); PxVec3 ra = contact.point - bodyFrame0.p; PxVec3 rb = contact.point - bodyFrame1.p; Vec3V targetVel = V3LoadU(contact.targetVel); const FloatV maxImpulse = FLoad(contact.maxImpulse); solverContact->scaledBiasX_targetVelocityY_maxImpulseZ = V3Merge(FMax(maxPen, FSub(separation, restDistance)), V3Dot(normalV,targetVel), maxImpulse); //TODO - should we do cross only in vector land and then store. Could cause a LHS but probably no worse than //what we already have (probably has a LHS from converting from vector to scalar above) const PxVec3 raXn = ra.cross(normal); const PxVec3 rbXn = rb.cross(normal); Cm::SpatialVector deltaV0, deltaV1; PxReal unitResponse = getImpulseResponse(b0, Cm::SpatialVector(normal, raXn), deltaV0, d0, angD0, b1, Cm::SpatialVector(-normal, -rbXn), deltaV1, d1, angD1); const PxReal vrel = b0.projectVelocity(normal, raXn) - b1.projectVelocity(normal, rbXn); solverContact->raXnXYZ_appliedForceW = V4SetW(Vec4V_From_Vec3V(V3LoadU(raXn)), zero); solverContact->rbXnXYZ_velMultiplierW = V4SetW(Vec4V_From_Vec3V(V3LoadU(rbXn)), zero); completeContactPoint(*solverContact, unitResponse, vrel, invDt, header->restitution, bounceThreshold); solverContact->setDeltaVA(deltaV0.linear, deltaV0.angular); solverContact->setDeltaVB(deltaV1.linear, deltaV1.angular); } ptr = p; } } //construct all the frictions PxU8* PX_RESTRICT ptr2 = workspace; const PxF32 orthoThreshold = 0.70710678f; const PxF32 eps = 0.00001f; bool hasFriction = false; for(PxU32 i=0;i< frictionPatchCount;i++) { const PxU32 contactCount = c.frictionPatchContactCounts[i]; if(contactCount == 0) continue; PxcSolverContactCoulombHeader* header = reinterpret_cast<PxcSolverContactCoulombHeader*>(ptr2); header->frictionOffset = PxU16(ptr - ptr2); ptr2 += sizeof(PxcSolverContactCoulombHeader) + header->numNormalConstr * pointStride; PxVec3 normal = c.frictionPatches[i].normal; const Gu::ContactPoint* contactBase0 = buffer.contacts + c.contactPatches[c.correlationListHeads[i]].start; const PxReal staticFriction = contactBase0->staticFriction; const PxU32 disableStrongFriction = contactBase0->internalFaceIndex1 & PxMaterialFlag::eDISABLE_FRICTION; const bool haveFriction = (disableStrongFriction == 0); PxcSolverFrictionHeader* frictionHeader = (PxcSolverFrictionHeader*)ptr; frictionHeader->numNormalConstr = Ps::to8(c.frictionPatchContactCounts[i]); frictionHeader->numFrictionConstr = Ps::to8(haveFriction ? c.frictionPatches[i].numConstraints : 0); ptr += sizeof(PxcSolverFrictionHeader); ptr += frictionHeader->getAppliedForcePaddingSize(c.frictionPatchContactCounts[i]); Ps::prefetchLine(ptr, 128); Ps::prefetchLine(ptr, 256); Ps::prefetchLine(ptr, 384); const PxVec3 t0Fallback1(0.f, -normal.z, normal.y); const PxVec3 t0Fallback2(-normal.y, normal.x, 0.f) ; const PxVec3 tFallback1 = orthoThreshold > PxAbs(normal.x) ? t0Fallback1 : t0Fallback2; const PxVec3 vrel = b0.getLinVel() - b1.getLinVel(); const PxVec3 t0_ = vrel - normal * (normal.dot(vrel)); const PxReal sqDist = t0_.dot(t0_); const PxVec3 tDir0 = (sqDist > eps ? t0_: tFallback1).getNormalized(); const PxVec3 tDir1 = tDir0.cross(normal); PxVec3 tFallback[2] = {tDir0, tDir1}; PxU32 ind = 0; if(haveFriction) { hasFriction = true; frictionHeader->setStaticFriction(staticFriction); frictionHeader->setDominance0(n.dominance0); frictionHeader->setDominance1(n.dominance1); frictionHeader->angDom0 = angD0; frictionHeader->angDom1 = angD1; frictionHeader->type = frictionHeaderType; PxU32 totalPatchContactCount = 0; for(PxU32 patch=c.correlationListHeads[i]; patch!=PxcCorrelationBuffer::LIST_END; patch = c.contactPatches[patch].next) { const PxU32 count = c.contactPatches[patch].count; const PxU32 start = c.contactPatches[patch].start; const Gu::ContactPoint* contactBase = buffer.contacts + start; PxU8* p = ptr; for(PxU32 j =0; j < count; j++) { const PxU32 contactId = totalPatchContactCount + j; const Gu::ContactPoint& contact = contactBase[j]; const PxVec3 ra = contact.point - bodyFrame0.p; const PxVec3 rb = contact.point - bodyFrame1.p; for(PxU32 k = 0; k < frictionCountPerPoint; ++k) { PxcSolverFrictionExt* PX_RESTRICT f0 = reinterpret_cast<PxcSolverFrictionExt*>(p); p += frictionStride; f0->contactIndex = contactId; PxVec3 t0 = tFallback[ind]; ind = 1 - ind; PxVec3 raXn = ra.cross(t0); PxVec3 rbXn = rb.cross(t0); Cm::SpatialVector deltaV0, deltaV1; PxReal unitResponse = getImpulseResponse(b0, Cm::SpatialVector(t0, raXn), deltaV0, d0, angD0, b1, Cm::SpatialVector(-t0, -rbXn), deltaV1, d1, angD1); f0->setVelMultiplier(FLoad(unitResponse>0.0f ? 1.f/unitResponse : 0.0f)); f0->setRaXn(raXn); f0->setRbXn(rbXn); f0->setNormal(t0); f0->setAppliedForce(0.0f); f0->setDeltaVA(deltaV0.linear, deltaV0.angular); f0->setDeltaVB(deltaV1.linear, deltaV1.angular); } } totalPatchContactCount += c.contactPatches[patch].count; ptr = p; } } } //PX_ASSERT(ptr - workspace == n.solverConstraintSize); return hasFriction; }
bool setupFinalizeExtSolverContactsCoulomb( const ContactBuffer& buffer, const CorrelationBuffer& c, const PxTransform& bodyFrame0, const PxTransform& bodyFrame1, PxU8* workspace, PxReal invDt, PxReal bounceThresholdF32, const SolverExtBody& b0, const SolverExtBody& b1, PxU32 frictionCountPerPoint, PxReal invMassScale0, PxReal invInertiaScale0, PxReal invMassScale1, PxReal invInertiaScale1, PxReal restDist, PxReal ccdMaxDistance) { // NOTE II: the friction patches are sparse (some of them have no contact patches, and // therefore did not get written back to the cache) but the patch addresses are dense, // corresponding to valid patches const FloatV ccdMaxSeparation = FLoad(ccdMaxDistance); PxU8* PX_RESTRICT ptr = workspace; //KS - TODO - this should all be done in SIMD to avoid LHS const PxF32 maxPenBias0 = b0.mLinkIndex == PxSolverConstraintDesc::NO_LINK ? b0.mBodyData->penBiasClamp : getMaxPenBias(*b0.mFsData)[b0.mLinkIndex]; const PxF32 maxPenBias1 = b1.mLinkIndex == PxSolverConstraintDesc::NO_LINK ? b1.mBodyData->penBiasClamp : getMaxPenBias(*b1.mFsData)[b1.mLinkIndex]; const FloatV maxPenBias = FLoad(PxMax(maxPenBias0, maxPenBias1)/invDt); const FloatV restDistance = FLoad(restDist); const FloatV bounceThreshold = FLoad(bounceThresholdF32); const FloatV invDtV = FLoad(invDt); const FloatV pt8 = FLoad(0.8f); const FloatV invDtp8 = FMul(invDtV, pt8); Ps::prefetchLine(c.contactID); Ps::prefetchLine(c.contactID, 128); const PxU32 frictionPatchCount = c.frictionPatchCount; const PxU32 pointStride = sizeof(SolverContactPointExt); const PxU32 frictionStride = sizeof(SolverContactFrictionExt); const PxU8 pointHeaderType = DY_SC_TYPE_EXT_CONTACT; const PxU8 frictionHeaderType = DY_SC_TYPE_EXT_FRICTION; PxReal d0 = invMassScale0; PxReal d1 = invMassScale1; PxReal angD0 = invInertiaScale0; PxReal angD1 = invInertiaScale1; PxU8 flags = 0; for(PxU32 i=0;i< frictionPatchCount;i++) { const PxU32 contactCount = c.frictionPatchContactCounts[i]; if(contactCount == 0) continue; const Gu::ContactPoint* contactBase0 = buffer.contacts + c.contactPatches[c.correlationListHeads[i]].start; const Vec3V normalV = Ps::aos::V3LoadA(contactBase0->normal); const Vec3V normal = V3LoadA(contactBase0->normal); const PxReal combinedRestitution = contactBase0->restitution; SolverContactCoulombHeader* PX_RESTRICT header = reinterpret_cast<SolverContactCoulombHeader*>(ptr); ptr += sizeof(SolverContactCoulombHeader); Ps::prefetchLine(ptr, 128); Ps::prefetchLine(ptr, 256); Ps::prefetchLine(ptr, 384); const FloatV restitution = FLoad(combinedRestitution); header->numNormalConstr = PxU8(contactCount); header->type = pointHeaderType; //header->setRestitution(combinedRestitution); header->setDominance0(d0); header->setDominance1(d1); header->angDom0 = angD0; header->angDom1 = angD1; header->flags = flags; header->setNormal(normalV); for(PxU32 patch=c.correlationListHeads[i]; patch!=CorrelationBuffer::LIST_END; patch = c.contactPatches[patch].next) { const PxU32 count = c.contactPatches[patch].count; const Gu::ContactPoint* contactBase = buffer.contacts + c.contactPatches[patch].start; PxU8* p = ptr; for(PxU32 j=0;j<count;j++) { const Gu::ContactPoint& contact = contactBase[j]; SolverContactPointExt* PX_RESTRICT solverContact = reinterpret_cast<SolverContactPointExt*>(p); p += pointStride; setupExtSolverContact(b0, b1, d0, d1, angD0, angD1, bodyFrame0, bodyFrame1, normal, invDtV, invDtp8, restDistance, maxPenBias, restitution, bounceThreshold, contact, *solverContact, ccdMaxSeparation); } ptr = p; } } //construct all the frictions PxU8* PX_RESTRICT ptr2 = workspace; const PxF32 orthoThreshold = 0.70710678f; const PxF32 eps = 0.00001f; bool hasFriction = false; for(PxU32 i=0;i< frictionPatchCount;i++) { const PxU32 contactCount = c.frictionPatchContactCounts[i]; if(contactCount == 0) continue; SolverContactCoulombHeader* header = reinterpret_cast<SolverContactCoulombHeader*>(ptr2); header->frictionOffset = PxU16(ptr - ptr2); ptr2 += sizeof(SolverContactCoulombHeader) + header->numNormalConstr * pointStride; const Gu::ContactPoint* contactBase0 = buffer.contacts + c.contactPatches[c.correlationListHeads[i]].start; PxVec3 normal = contactBase0->normal; const PxReal staticFriction = contactBase0->staticFriction; const bool disableStrongFriction = !!(contactBase0->materialFlags & PxMaterialFlag::eDISABLE_FRICTION); const bool haveFriction = (disableStrongFriction == 0); SolverFrictionHeader* frictionHeader = reinterpret_cast<SolverFrictionHeader*>(ptr); frictionHeader->numNormalConstr = Ps::to8(c.frictionPatchContactCounts[i]); frictionHeader->numFrictionConstr = Ps::to8(haveFriction ? c.frictionPatchContactCounts[i] * frictionCountPerPoint : 0); frictionHeader->flags = flags; ptr += sizeof(SolverFrictionHeader); PxF32* forceBuffer = reinterpret_cast<PxF32*>(ptr); ptr += frictionHeader->getAppliedForcePaddingSize(c.frictionPatchContactCounts[i]); PxMemZero(forceBuffer, sizeof(PxF32) * c.frictionPatchContactCounts[i]); Ps::prefetchLine(ptr, 128); Ps::prefetchLine(ptr, 256); Ps::prefetchLine(ptr, 384); const PxVec3 t0Fallback1(0.f, -normal.z, normal.y); const PxVec3 t0Fallback2(-normal.y, normal.x, 0.f) ; const PxVec3 tFallback1 = orthoThreshold > PxAbs(normal.x) ? t0Fallback1 : t0Fallback2; const PxVec3 vrel = b0.getLinVel() - b1.getLinVel(); const PxVec3 t0_ = vrel - normal * (normal.dot(vrel)); const PxReal sqDist = t0_.dot(t0_); const PxVec3 tDir0 = (sqDist > eps ? t0_: tFallback1).getNormalized(); const PxVec3 tDir1 = tDir0.cross(normal); PxVec3 tFallback[2] = {tDir0, tDir1}; PxU32 ind = 0; if(haveFriction) { hasFriction = true; frictionHeader->setStaticFriction(staticFriction); frictionHeader->invMass0D0 = d0; frictionHeader->invMass1D1 = d1; frictionHeader->angDom0 = angD0; frictionHeader->angDom1 = angD1; frictionHeader->type = frictionHeaderType; PxU32 totalPatchContactCount = 0; for(PxU32 patch=c.correlationListHeads[i]; patch!=CorrelationBuffer::LIST_END; patch = c.contactPatches[patch].next) { const PxU32 count = c.contactPatches[patch].count; const PxU32 start = c.contactPatches[patch].start; const Gu::ContactPoint* contactBase = buffer.contacts + start; PxU8* p = ptr; for(PxU32 j =0; j < count; j++) { const Gu::ContactPoint& contact = contactBase[j]; const PxVec3 ra = contact.point - bodyFrame0.p; const PxVec3 rb = contact.point - bodyFrame1.p; const PxVec3 targetVel = contact.targetVel; const PxVec3 pVRa = b0.getLinVel() + b0.getAngVel().cross(ra); const PxVec3 pVRb = b1.getLinVel() + b1.getAngVel().cross(rb); //const PxVec3 vrel = pVRa - pVRb; for(PxU32 k = 0; k < frictionCountPerPoint; ++k) { SolverContactFrictionExt* PX_RESTRICT f0 = reinterpret_cast<SolverContactFrictionExt*>(p); p += frictionStride; PxVec3 t0 = tFallback[ind]; ind = 1 - ind; PxVec3 raXn = ra.cross(t0); PxVec3 rbXn = rb.cross(t0); Cm::SpatialVector deltaV0, deltaV1; const Cm::SpatialVector resp0 = createImpulseResponseVector(t0, raXn, b0); const Cm::SpatialVector resp1 = createImpulseResponseVector(-t0, -rbXn, b1); PxReal unitResponse = getImpulseResponse(b0, resp0, deltaV0, d0, angD0, b1, resp1, deltaV1, d1, angD1); PxReal tv = targetVel.dot(t0); if(b0.mLinkIndex == PxSolverConstraintDesc::NO_LINK) tv += pVRa.dot(t0); else if(b1.mLinkIndex == PxSolverConstraintDesc::NO_LINK) tv -= pVRb.dot(t0); f0->setVelMultiplier(FLoad(unitResponse>0.0f ? 1.f/unitResponse : 0.0f)); f0->setRaXn(resp0.angular); f0->setRbXn(-resp1.angular); f0->targetVel = tv; f0->setNormal(t0); f0->setAppliedForce(0.0f); f0->linDeltaVA = V3LoadA(deltaV0.linear); f0->angDeltaVA = V3LoadA(deltaV0.angular); f0->linDeltaVB = V3LoadA(deltaV1.linear); f0->angDeltaVB = V3LoadA(deltaV1.angular); } } totalPatchContactCount += c.contactPatches[patch].count; ptr = p; } } } //PX_ASSERT(ptr - workspace == n.solverConstraintSize); return hasFriction; }
void VisualDebugger::updatePvdProperties(const PxConvexMesh* convexMesh) { PVD::PvdCommLayerError error; PxReal mass; PxMat33Legacy localInertia; PxVec3 localCom; convexMesh->getMassInformation(mass, reinterpret_cast<PxMat33 &>(localInertia), localCom); PxU64 theInstance(PX_PROFILE_POINTER_TO_U64(convexMesh)); mPvdConnectionHelper.addPropertyGroupProperty(ConvexMeshProp::Mass, mass); mPvdConnectionHelper.addPropertyGroupProperty(ConvexMeshProp::LocalInertia, toPvdType(localInertia.toQuat())); mPvdConnectionHelper.addPropertyGroupProperty(ConvexMeshProp::LocalCenterOfMass, toPvdType(localCom)); mPvdConnectionHelper.sendSinglePropertyGroup(mPvdConnection, theInstance, PvdClassKeys::ConvexMesh); // update arrays: // vertex Array: { const PxU8* vertexPtr = reinterpret_cast<const PxU8*>(convexMesh->getVertices()); const PxU32 vertexStride = sizeof(PxVec3); const PxU32 numVertices = convexMesh->getNbVertices(); error = PvdConnectionHelper::sendSingleElementArrayProperty(mPvdConnection, theInstance, ConvexMeshProp::VertexArray , VectorArrayProp::Element, PVD::PvdCommLayerDatatype::Float3 , vertexPtr, vertexStride, numVertices); PX_ASSERT(error == PVD::PvdCommLayerError::None); } // HullPolyArray: PxU16 maxIndices = 0; { PxU32 properties[HullPolygonArrayProp::NUM_ELEMENTS]; PVD::PvdCommLayerDatatype dataTypes[HullPolygonArrayProp::NUM_ELEMENTS] = { PVD::PvdCommLayerDatatype::Plane, PVD::PvdCommLayerDatatype::U16, PVD::PvdCommLayerDatatype::U16}; for(PxU32 i = 0; i < HullPolygonArrayProp::NUM_ELEMENTS; i++) properties[i] = i+1; error = mPvdConnection->beginArrayPropertyBlock(theInstance, ConvexMeshProp::HullPolygonArray+1, properties, dataTypes, HullPolygonArrayProp::NUM_ELEMENTS); static const PxU32 NUM_STACK_ELT = 32; PX_ALLOCA(stack, PxHullPolygon, NUM_STACK_ELT); PxHullPolygon* pxHullPolygons = stack; PxHullPolygon* pxHullPolygonsEnd = pxHullPolygons+NUM_STACK_ELT; PxHullPolygon* curOut = pxHullPolygons; PxU32 numPolygons = convexMesh->getNbPolygons(); for(PxU32 index = 0; index < numPolygons; index++) { convexMesh->getPolygonData(index, *curOut); maxIndices = PxMax(maxIndices, PxU16(curOut->mIndexBase + curOut->mNbVerts)); curOut++; if(curOut == pxHullPolygonsEnd) { error = mPvdConnection->sendArrayObjects((PxU8*)(pxHullPolygons), sizeof(PxHullPolygon), NUM_STACK_ELT); curOut = pxHullPolygons; } } if(curOut != pxHullPolygons) error = mPvdConnection->sendArrayObjects((PxU8*)(pxHullPolygons), sizeof(PxHullPolygon), PxU32(curOut-pxHullPolygons)); error = mPvdConnection->endArrayPropertyBlock(); } // poly index Array: { const PxU8* indices = convexMesh->getIndexBuffer(); PxU32 indexCount = maxIndices; error = PvdConnectionHelper::sendSingleElementArrayProperty(mPvdConnection, theInstance, ConvexMeshProp::IndexArray , U8ArrayProp::Element, PVD::PvdCommLayerDatatype::U8 , indices, sizeof(PxU8), indexCount); PX_ASSERT(error == PVD::PvdCommLayerError::None); } }