//================================================================================= // Single closest hit compound sweep bool PxRigidBodyExt::linearSweepSingle( PxRigidBody& body, PxScene& scene, const PxVec3& unitDir, const PxReal distance, PxHitFlags outputFlags, PxSweepHit& closestHit, PxU32& shapeIndex, const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall, const PxQueryCache* cache, const PxReal inflation) { shapeIndex = 0xFFFFffff; PxReal closestDist = distance; PxU32 nbShapes = body.getNbShapes(); for(PxU32 i=0; i < nbShapes; i++) { PxShape* shape = NULL; body.getShapes(&shape, 1, i); PX_ASSERT(shape != NULL); PxTransform pose = PxShapeExt::getGlobalPose(*shape, body); PxQueryFilterData fd; fd.flags = filterData.flags; PxU32 or4 = (filterData.data.word0 | filterData.data.word1 | filterData.data.word2 | filterData.data.word3); fd.data = or4 ? filterData.data : shape->getSimulationFilterData(); PxGeometryHolder anyGeom = shape->getGeometry(); PxSweepBuffer subHit; // touching hits are not allowed to be returned from the filters scene.sweep(anyGeom.any(), pose, unitDir, distance, subHit, outputFlags, fd, filterCall, cache, inflation); if (subHit.hasBlock && subHit.block.distance < closestDist) { closestDist = subHit.block.distance; closestHit = subHit.block; shapeIndex = i; } } return (shapeIndex != 0xFFFFffff); }
void PxScaleRigidActor(PxRigidActor& actor, PxReal scale, bool scaleMassProps) { PX_CHECK_AND_RETURN(scale > 0, "PxScaleRigidActor requires that the scale parameter is greater than zero"); Ps::InlineArray<PxShape*, 64> shapes; shapes.resize(actor.getNbShapes()); actor.getShapes(shapes.begin(), shapes.size()); for(PxU32 i=0;i<shapes.size();i++) { shapes[i]->setLocalPose(scalePosition(shapes[i]->getLocalPose(), scale)); PxGeometryHolder h = shapes[i]->getGeometry(); switch(h.getType()) { case PxGeometryType::eSPHERE: h.sphere().radius *= scale; break; case PxGeometryType::ePLANE: break; case PxGeometryType::eCAPSULE: h.capsule().halfHeight *= scale; h.capsule().radius *= scale; break; case PxGeometryType::eBOX: h.box().halfExtents *= scale; break; case PxGeometryType::eCONVEXMESH: h.convexMesh().scale.scale *= scale; break; case PxGeometryType::eTRIANGLEMESH: h.triangleMesh().scale.scale *= scale; break; case PxGeometryType::eHEIGHTFIELD: h.heightField().heightScale *= scale; h.heightField().rowScale *= scale; h.heightField().columnScale *= scale; break; case PxGeometryType::eINVALID: case PxGeometryType::eGEOMETRY_COUNT: default: PX_ASSERT(0); } shapes[i]->setGeometry(h.any()); } if(!scaleMassProps) return; PxRigidDynamic* dynamic = (&actor)->is<PxRigidDynamic>(); if(!dynamic) return; PxReal scale3 = scale*scale*scale; dynamic->setMass(dynamic->getMass()*scale3); dynamic->setMassSpaceInertiaTensor(dynamic->getMassSpaceInertiaTensor()*scale3*scale*scale); dynamic->setCMassLocalPose(scalePosition(dynamic->getCMassLocalPose(), scale)); }
void SampleSubmarine::explode(PxRigidActor* actor, const PxVec3& explosionPos, const PxReal explosionStrength) { size_t numRenderActors = mRenderActors.size(); for(PxU32 i = 0; i < numRenderActors; i++) { if(&(mRenderActors[i]->getPhysicsShape()->getActor()) == actor) { PxShape* shape = mRenderActors[i]->getPhysicsShape(); PxTransform pose = PxShapeExt::getGlobalPose(*shape); PxGeometryHolder geom = shape->getGeometry(); // create new actor from shape (to split compound) PxRigidDynamic* newActor = mPhysics->createRigidDynamic(pose); if(!newActor) fatalError("createRigidDynamic failed!"); PxShape* newShape = newActor->createShape(geom.any(), *mMaterial); newShape->userData = mRenderActors[i]; mRenderActors[i]->setPhysicsShape(newShape); newActor->setActorFlag(PxActorFlag::eVISUALIZATION, true); newActor->setLinearDamping(10.5f); newActor->setAngularDamping(0.5f); PxRigidBodyExt::updateMassAndInertia(*newActor, 1.0f); mScene->addActor(*newActor); mPhysicsActors.push_back(newActor); PxVec3 explosion = pose.p - explosionPos; PxReal len = explosion.normalize(); explosion *= (explosionStrength / len); newActor->setLinearVelocity(explosion); newActor->setAngularVelocity(PxVec3(1,2,3)); } } removeActor(actor); }
void GLUTGame::RenderGeometry(PxGeometryHolder h, bool textured) { switch (h.getType()) { case PxGeometryType::eBOX: glScalef(h.box().halfExtents.x, h.box().halfExtents.y, h.box().halfExtents.z); if (textured) RenderTexturedCube(2.0f); else glutSolidCube(2.0f); break; case PxGeometryType::eSPHERE: glutSolidSphere(h.sphere().radius, RENDER_DETAIL, RENDER_DETAIL); break; case PxGeometryType::eCONVEXMESH: PxConvexMesh* mesh = h.convexMesh().convexMesh; const PxU32 nbPolys = mesh->getNbPolygons(); const PxU8* polygons = mesh->getIndexBuffer(); const PxVec3* verts = mesh->getVertices(); PxU32 numTotalTriangles = 0; for (PxU32 i = 0; i < nbPolys; i++) { PxHullPolygon data; mesh->getPolygonData(i, data); const PxU32 nbTris = data.mNbVerts - 2; const PxU8 vref0 = polygons[data.mIndexBase + 0]; for (PxU32 j = 0; j < nbTris; j++) { const PxU32 vref1 = polygons[data.mIndexBase + 0 + j + 1]; const PxU32 vref2 = polygons[data.mIndexBase + 0 + j + 2]; if (numTotalTriangles < MAX_NUM_CONVEXMESH_TRIANGLES) { gConvexMeshTriIndices[3 * numTotalTriangles + 0] = vref0; gConvexMeshTriIndices[3 * numTotalTriangles + 1] = vref1; gConvexMeshTriIndices[3 * numTotalTriangles + 2] = vref2; numTotalTriangles++; } } } if (numTotalTriangles < MAX_NUM_CONVEXMESH_TRIANGLES) { glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, 0, verts); glDrawElements(GL_TRIANGLES, numTotalTriangles * 3, GL_UNSIGNED_INT, gConvexMeshTriIndices); glDisableClientState(GL_VERTEX_ARRAY); } } }
//================================================================================= // Multiple hits compound sweep // AP: we might be able to improve the return results API but no time for it in 3.3 PxU32 PxRigidBodyExt::linearSweepMultiple( PxRigidBody& body, PxScene& scene, const PxVec3& unitDir, const PxReal distance, PxHitFlags outputFlags, PxSweepHit* hitBuffer, PxU32* hitShapeIndices, PxU32 hitBufferSize, PxSweepHit& block, PxI32& blockingHitShapeIndex, bool& overflow, const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall, const PxQueryCache* cache, const PxReal inflation) { overflow = false; blockingHitShapeIndex = -1; for (PxU32 i = 0; i < hitBufferSize; i++) hitShapeIndices[i] = 0xFFFFffff; PxI32 sumNbResults = 0; PxU32 nbShapes = body.getNbShapes(); PxF32 shrunkMaxDistance = distance; for(PxU32 i=0; i < nbShapes; i++) { PxShape* shape = NULL; body.getShapes(&shape, 1, i); PX_ASSERT(shape != NULL); PxTransform pose = PxShapeExt::getGlobalPose(*shape, body); PxQueryFilterData fd; fd.flags = filterData.flags; PxU32 or4 = (filterData.data.word0 | filterData.data.word1 | filterData.data.word2 | filterData.data.word3); fd.data = or4 ? filterData.data : shape->getSimulationFilterData(); PxGeometryHolder anyGeom = shape->getGeometry(); PxU32 bufSizeLeft = hitBufferSize-sumNbResults; PxSweepHit extraHit; PxSweepBuffer buffer(bufSizeLeft == 0 ? &extraHit : hitBuffer+sumNbResults, bufSizeLeft == 0 ? 1 : hitBufferSize-sumNbResults); scene.sweep(anyGeom.any(), pose, unitDir, shrunkMaxDistance, buffer, outputFlags, fd, filterCall, cache, inflation); // Check and abort on overflow. Assume overflow if result count is bufSize. PxU32 nbNewResults = buffer.getNbTouches(); overflow |= (nbNewResults >= bufSizeLeft); if (bufSizeLeft == 0) // this is for when we used the extraHit buffer nbNewResults = 0; // set hitShapeIndices for each new non-blocking hit for (PxU32 j = 0; j < nbNewResults; j++) if (sumNbResults + PxU32(j) < hitBufferSize) hitShapeIndices[sumNbResults+j] = i; if (buffer.hasBlock) // there's a blocking hit in the most recent sweepMultiple results { // overwrite the return result blocking hit with the new blocking hit if under if (blockingHitShapeIndex == -1 || buffer.block.distance < block.distance) { blockingHitShapeIndex = (PxI32)i; block = buffer.block; } // Remove all the old touching hits below the new maxDist // sumNbResults is not updated yet at this point // and represents the count accumulated so far excluding the very last query PxI32 nbNewResultsSigned = PxI32(nbNewResults); // need a signed version, see nbNewResultsSigned-- below for (PxI32 j = sumNbResults-1; j >= 0; j--) // iterate over "old" hits (up to shapeIndex-1) if (buffer.block.distance < hitBuffer[j].distance) { // overwrite with last "new" hit PxI32 sourceIndex = PxI32(sumNbResults)+nbNewResultsSigned-1; PX_ASSERT(sourceIndex >= j); hitBuffer[j] = hitBuffer[sourceIndex]; hitShapeIndices[j] = hitShapeIndices[sourceIndex]; nbNewResultsSigned--; // can get negative, that means we are shifting the last results array } sumNbResults += nbNewResultsSigned; } else // if there was no new blocking hit we don't need to do anything special, simply append all results to touch array sumNbResults += nbNewResults; PX_ASSERT(sumNbResults >= 0 && sumNbResults <= PxI32(hitBufferSize)); } return (PxU32)sumNbResults; }