void Sc::ShapeSim::getFilterInfo(PxFilterObjectAttributes& filterAttr, PxFilterData& filterData) const { filterAttr = 0; const PxShapeFlags flags = mCore.getFlags(); if (hasTriggerFlags(flags)) filterAttr |= PxFilterObjectFlag::eTRIGGER; BodySim* b = getBodySim(); if (b) { if (!b->isArticulationLink()) { if (b->isKinematic()) filterAttr |= PxFilterObjectFlag::eKINEMATIC; setFilterObjectAttributeType(filterAttr, PxFilterObjectType::eRIGID_DYNAMIC); } else setFilterObjectAttributeType(filterAttr, PxFilterObjectType::eARTICULATION); } else { setFilterObjectAttributeType(filterAttr, PxFilterObjectType::eRIGID_STATIC); } filterData = mCore.getSimulationFilterData(); }
void Sc::ConstraintProjectionTree::rankConstraint(ConstraintSim& c, BodyRank& br, PxU32& dominanceTracking, PxU32& constraintsToProjectCount) { PxU32 projectToBody, projectToOtherBody; BodySim* otherB; getConstraintStatus(c, br.startingNode->body, otherB, projectToBody, projectToOtherBody); if (isFixedBody(otherB)) // joint to fixed anchor { PxU32 rank; if (projectToOtherBody) { dominanceTracking = 0; // makes sure that the flags below will never get raised again for the body br.rank &= ~(BodyRank::sAllDominantDynamic | BodyRank::sDominantDynamic); rank = BodyRank::sOneWayProjection; //we should prefer picking projected constraints as the root over non-projected ones. constraintsToProjectCount++; } else rank = 0; if (!otherB) rank |= BodyRank::sAttachedToStatic; else { PX_ASSERT(otherB->isKinematic()); rank |= BodyRank::sAttachedToKinematic; } // the highest ranked fixed anchor constraint should get tracked if ((!br.constraintToFixedAnchor) || (rank > br.rank)) br.constraintToFixedAnchor = &c; br.rank |= rank; } else { if (projectToBody && projectToOtherBody) { dominanceTracking &= ~BodyRank::sAllDominantDynamic; // makes sure that from now on this will never get raised again for the body br.rank &= ~BodyRank::sAllDominantDynamic; constraintsToProjectCount++; } else if (projectToOtherBody) { dominanceTracking &= ~(BodyRank::sAllDominantDynamic | BodyRank::sDominantDynamic); // makes sure that from now on these will never get raised again for the body br.rank &= ~(BodyRank::sAllDominantDynamic | BodyRank::sDominantDynamic); constraintsToProjectCount++; } else if (projectToBody) { br.rank |= BodyRank::sOneWayProjection | (dominanceTracking & (BodyRank::sAllDominantDynamic | BodyRank::sDominantDynamic)); constraintsToProjectCount++; } br.rank += BodyRank::sAttachedToDynamic; } }
void Sc::ArticulationSim::addBody(BodySim& body, BodySim* parent, ArticulationJointSim* joint) { mBodies.pushBack(&body); mJoints.pushBack(joint); mAcceleration.pushBack(Cm::SpatialVector(PxVec3(0.f), PxVec3(0.f))); PxU32 index = mLinks.size(); PX_ASSERT((((index==0) && (joint == 0)) && (parent == 0)) || (((index!=0) && joint) && (parent && (parent->getArticulation() == this)))); ArticulationLink &link = mLinks.insert(); link.body = &body.getLowLevelBody(); link.bodyCore = &body.getBodyCore().getCore(); link.children = 0; bool shouldSleep; bool currentlyAsleep; bool bodyReadyForSleep = body.checkSleepReadinessBesidesWakeCounter(); PxReal wakeCounter = getCore().getWakeCounter(); if(parent) { currentlyAsleep = !mBodies[0]->isActive(); shouldSleep = currentlyAsleep && bodyReadyForSleep; PxU32 parentIndex = findBodyIndex(*parent); link.parent = parentIndex; link.pathToRoot = mLinks[parentIndex].pathToRoot | ArticulationBitField(1)<<index; link.inboundJoint = &joint->getCore().getCore(); mLinks[parentIndex].children |= ArticulationBitField(1)<<index; } else { currentlyAsleep = (wakeCounter == 0.0f); shouldSleep = currentlyAsleep && bodyReadyForSleep; link.parent = DY_ARTICULATION_LINK_NONE; link.pathToRoot = 1; link.inboundJoint = NULL; } if (currentlyAsleep && (!shouldSleep)) { for(PxU32 i=0; i < (mBodies.size() - 1); i++) mBodies[i]->internalWakeUpArticulationLink(wakeCounter); } body.setArticulation(this, wakeCounter, shouldSleep, index); mUpdateSolverData = true; }
PxU32 Sc::ConstraintProjectionTree::projectionTreeBuildStep(ConstraintGroupNode& node, ConstraintSim* cToParent, ConstraintGroupNode** nodeQueue) { PX_ASSERT(node.readFlag(ConstraintGroupNode::eDISCOVERED)); PxU32 nodeQueueFillCount = 0; //go through all constraints attached to the body. BodySim* body = node.body; PxU32 size = body->getActorInteractionCount(); Sc::Interaction** interactions = body->getActorInteractions(); while(size--) { Interaction* interaction = *interactions++; if (interaction->getType() == InteractionType::eCONSTRAINTSHADER) { ConstraintSim* c = static_cast<ConstraintInteraction*>(interaction)->getConstraint(); if (c != cToParent) //don't go back along the edge we came from (not really necessary I guess since the ConstraintGroupNode::eDISCOVERED marker should solve this) { PxU32 projectToBody, projectToOtherBody; BodySim* neighbor; getConstraintStatus(*c, body, neighbor, projectToBody, projectToOtherBody); if(!isFixedBody(neighbor) && (!projectToOtherBody || projectToBody)) //just ignore the eventual constraint with environment over here. Body might be attached to multiple fixed anchors. //Also make sure to ignore one-way projection that goes the opposite way. { ConstraintGroupNode* neighborNode = neighbor->getConstraintGroup(); PX_ASSERT(neighborNode); if (!neighborNode->readFlag(ConstraintGroupNode::eDISCOVERED)) { *nodeQueue = neighborNode; neighborNode->initProjectionData(&node, c); neighborNode->raiseFlag(ConstraintGroupNode::eDISCOVERED); //flag body nodes that we process so we can detect loops nodeQueueFillCount++; nodeQueue++; } } } } } return nodeQueueFillCount; }
bool Sc::ShapeSim::destroyLowLevelVolume() { //Need to test that shape has entry in bp. The shape might not have a bp //entry because it has its simulation flag set to false. const PxcBpHandle actorHandle = getAABBMgrId().mActorHandle; if(PX_INVALID_BP_HANDLE!=actorHandle) { getInteractionScene().getLowLevelContext()->unMarkShape(actorHandle); } bool removingLastShape=Element::destroyLowLevelVolume(); if(removingLastShape) { BodySim* b = getBodySim(); if(b) b->getLowLevelBody().resetAABBMgrId(); } return removingLastShape; }
void Sc::ArticulationSim::removeBody(BodySim &body) { PX_ASSERT(body.getArticulation() == this); PxU32 index = findBodyIndex(body); body.setArticulation(NULL, 0.0f, true, 0); ArticulationLink &link0 = mLinks[index]; PX_ASSERT(link0.children == 0); PX_UNUSED(link0); // copy all the later links down by one for(PxU32 i=index+1;i<mLinks.size();i++) { mLinks[i-1] = mLinks[i]; mBodies[i-1] = mBodies[i]; mJoints[i-1] = mJoints[i]; //setIslandHandle(*mBodies[i-1], i-1); } // adjust parent/child indices ArticulationBitField fixedIndices = (ArticulationBitField(1)<<index)-1; ArticulationBitField shiftIndices = ~(fixedIndices|(ArticulationBitField(1)<<index)); for(PxU32 i=0;i<mLinks.size();i++) { ArticulationLink &link = mLinks[i]; if(link.parent != DY_ARTICULATION_LINK_NONE && link.parent>index) link.pathToRoot = (link.pathToRoot&fixedIndices) | (link.pathToRoot&shiftIndices)>>1; link.children = (link.children&fixedIndices) | (link.children&shiftIndices)>>1; } mLinks.popBack(); mUpdateSolverData = true; }