void SampleCharacterCloth::resetCape() { PxCloth& cloth = *mCape; // compute cloth pose and collider positions PxTransform rootPose; SampleArray<PxVec3> positions; SampleArray<PxU32> indexPairs; mCharacter.getFramePose(rootPose, positions, indexPairs); // set cloth pose cloth.setGlobalPose(rootPose); // set collision sphere positions SampleArray<PxClothCollisionSphere> spheres(positions.size()); SampleArray<PxClothCollisionPlane> planes(cloth.getNbCollisionPlanes()); SampleArray<PxU32> convexMasks(cloth.getNbCollisionConvexes()); cloth.getCollisionData(spheres.begin(), indexPairs.begin(), planes.begin(), convexMasks.begin()); for (PxU32 i = 0; i < positions.size(); i++) spheres[i].pos = positions[i]; cloth.setCollisionSpheres(spheres.begin()); // set positions for constrained particles SampleArray<PxVec3> particlePositions; mSkin.computeNewPositions(mCharacter, particlePositions); Test::ClothHelpers::setParticlePositions(cloth, particlePositions, false, false); cloth.setExternalAcceleration(PxVec3(0.0f)); // clear previous state of collision shapes etc. cloth.clearInterpolation(); }
bool Acclaim::readAMCData(const char* filename, Acclaim::ASFData& asfData, Acclaim::AMCData& amcData) { using namespace Acclaim; char token[MAX_TOKEN_LENGTH]; SampleArray<FrameData> tempFrameData; tempFrameData.reserve(300); FILE* fp = fopen(filename, "r"); if (!fp) return false; SampleFileBuffer buffer(fp); while (buffer.getNextToken(token, false) == true) { if (token[0] == '#') // comment { buffer.skipUntilNextLine(); continue; } else if (token[0] == ':') // blocks { const char* str = token + 1; // remainder of the string if (strcmp(str, "FULLY-SPECIFIED") == 0) continue; else if (strcmp(str, "DEGREES") == 0) continue; } else if (isNumeric(token[0]) == true) { // frame number int frameNo = atoi(token); FrameData frameData; if (readFrameData(buffer, asfData, frameData) == true) tempFrameData.pushBack(frameData); } } amcData.mNbFrames = tempFrameData.size(); amcData.mFrameData = (FrameData*)malloc(sizeof(FrameData) * amcData.mNbFrames); memcpy(amcData.mFrameData, tempFrameData.begin(), sizeof(FrameData) * amcData.mNbFrames); fclose(fp); return true; }
void SampleCharacterCloth::updateCape(float dtime) { PxCloth& cloth = *mCape; // compute cloth pose and collider positions PxTransform rootPose; SampleArray<PxVec3> positions; SampleArray<PxU32> indexPairs; mCharacter.getFramePose(rootPose, positions, indexPairs); // set cloth pose cloth.setTargetPose(rootPose); // set collision sphere positions SampleArray<PxClothCollisionSphere> spheres(positions.size()); SampleArray<PxClothCollisionPlane> planes(cloth.getNbCollisionPlanes()); SampleArray<PxU32> convexMasks(cloth.getNbCollisionConvexes()); cloth.getCollisionData(spheres.begin(), indexPairs.begin(), planes.begin(), convexMasks.begin()); for (PxU32 i = 0; i < positions.size(); i++) spheres[i].pos = positions[i]; cloth.setCollisionSpheres(spheres.begin()); // set positions for constrained particles SampleArray<PxVec3> particlePositions; mSkin.computeNewPositions(mCharacter, particlePositions); Test::ClothHelpers::setParticlePositions(cloth, particlePositions, true, true); // add wind while in freefall if (mJump.isInFreefall()) { PxReal strength = 20.0f; PxVec3 offset( PxReal(PxToolkit::Rand(-1,1)), 1.0f + PxReal(PxToolkit::Rand(-1,1)), PxReal(PxToolkit::Rand(-1,1))); PxVec3 windAcceleration = strength * offset; cloth.setExternalAcceleration(windAcceleration); } }
bool Skin::bindToCharacter(Character &character, SampleArray<PxVec4> &positions) { // currently we just bind everything to the 'thorax' (between neck and clavicles). // Modify this if you need to do more elaborate skin binding mBindPos.resize(positions.size()); Acclaim::Bone* bone = getBoneFromName(*character.mASFData, "thorax"); if (bone == NULL) return false; PxTransform boneTransform = computeBoneTransformRest(*bone); PxTransform boneTransformInv = boneTransform.getInverse(); mBoneID = bone->mID - 1; for (PxU32 i = 0; i < positions.size(); i++) { mBindPos[i] = boneTransformInv.transform( reinterpret_cast<const PxVec3&>(positions[i])); } return true; }
void Test::TestGroup::getPathName(char* strBuffer, unsigned strBufferMaxLength, bool omitRoot) { SampleArray<TestGroup*> path; getPath(path); unsigned charCount = 1; //\0 for (unsigned i = omitRoot ? 1 : 0; i < path.size(); ++i) { const TestGroup& node = *path[i]; unsigned nodeNameLength = unsigned(strlen(node.getName())); if (node.getFirstChild()) nodeNameLength += 1; if (charCount + nodeNameLength < strBufferMaxLength) { sprintf(strBuffer + (charCount - 1), "%s%s", node.getName(), node.getFirstChild() ? "/" : ""); charCount += nodeNameLength; } } }
void SampleCharacterCloth::createCape() { // compute root transform and positions of all the bones PxTransform rootPose; SampleArray<PxVec3> positions; SampleArray<PxU32> indexPairs; mCharacter.getFramePose(rootPose, positions, indexPairs); // convert bones to collision capsules SampleArray<PxClothCollisionSphere> spheres; spheres.resize(positions.size()); for (PxU32 i = 0; i < positions.size(); i++) { spheres[i].pos = positions[i]; spheres[i].radius = gCharacterScale * gSphereRadius[i]; } PxClothCollisionData collisionData; collisionData.numSpheres = static_cast<PxU32>(positions.size()); collisionData.spheres = spheres.begin(); collisionData.numPairs = static_cast<PxU32>(indexPairs.size()) / 2; // number of capsules collisionData.pairIndexBuffer = indexPairs.begin(); // create the cloth cape mesh from file PxClothMeshDesc meshDesc; SampleArray<PxVec3> vertices; SampleArray<PxU32> primitives; SampleArray<PxReal> uvs; const char* capeFileName = getSampleMediaFilename("ctdm_cape_m.obj"); PxReal clothScale = gCharacterScale * 0.3f; PxVec3 offset = PxVec3(0,-1.5,0); PxQuat rot = PxQuat(0, PxVec3(0,1,0)); Test::ClothHelpers::createMeshFromObj(capeFileName, clothScale, &rot, &offset, vertices, primitives, &uvs, meshDesc); if (!meshDesc.isValid()) fatalError("Could not load ctdm_cape_m.obj\n"); // create the cloth PxCloth& cloth = *createClothFromMeshDesc( meshDesc, rootPose, &collisionData, PxVec3(0,-1,0), uvs.begin(), "dummy_cape_d.bmp", PxVec3(0.5f, 0.5f, 0.5f), 0.8f); mCape = &cloth; // attach top verts PxClothReadData* readData = cloth.lockClothReadData(); PX_ASSERT(readData); PxU32 numParticles = cloth.getNbParticles(); SampleArray<PxClothParticle> particles(numParticles); SampleArray<PxVec3> particlePositions(numParticles); for(PxU32 i = 0; i < numParticles; i++) { particles[i].pos = readData->particles[i].pos; particles[i].invWeight = (uvs[i*2+1] > 0.85f) ? 0.0f : readData->particles[i].invWeight; particlePositions[i] = readData->particles[i].pos; } readData->unlock(); cloth.setParticles(particles.begin(), particles.begin()); // compute initial skin binding to the character mSkin.bindToCharacter(mCharacter, particlePositions); // set solver settings cloth.setSolverFrequency(240); // damp global particle velocity to 90% every 0.1 seconds cloth.setDampingCoefficient(0.1f); // damp local particle velocity cloth.setDragCoefficient(0.1f); // transfer frame velocity // reduce effect of local frame acceleration cloth.setInertiaScale(0.3f); const bool useVirtualParticles = true; const bool useSweptContact = true; const bool useCustomConfig = true; // virtual particles if (useVirtualParticles) Test::ClothHelpers::createVirtualParticles(cloth, meshDesc, 4); // ccd cloth.setClothFlag(PxClothFlag::eSWEPT_CONTACT, useSweptContact); // use GPU or not #if PX_SUPPORT_GPU_PHYSX cloth.setClothFlag(PxClothFlag::eGPU, mUseGPU); #endif // custom fiber configuration if (useCustomConfig) { PxClothPhaseSolverConfig config; config = cloth.getPhaseSolverConfig(PxClothFabricPhaseType::eSTRETCHING); config.solverType = PxClothPhaseSolverConfig::eSTIFF; config.stiffness = 1.0f; cloth.setPhaseSolverConfig(PxClothFabricPhaseType::eSTRETCHING, config); config = cloth.getPhaseSolverConfig(PxClothFabricPhaseType::eSTRETCHING_HORIZONTAL); config.solverType = PxClothPhaseSolverConfig::eFAST; config.stiffness = 1.0f; cloth.setPhaseSolverConfig(PxClothFabricPhaseType::eSTRETCHING_HORIZONTAL, config); config = cloth.getPhaseSolverConfig(PxClothFabricPhaseType::eSHEARING); config.solverType = PxClothPhaseSolverConfig::eFAST; config.stiffness = 0.75f; cloth.setPhaseSolverConfig(PxClothFabricPhaseType::eSHEARING, config); config = cloth.getPhaseSolverConfig(PxClothFabricPhaseType::eBENDING_ANGLE); config.solverType = PxClothPhaseSolverConfig::eBENDING; config.stiffness = 0.5f; cloth.setPhaseSolverConfig(PxClothFabricPhaseType::eBENDING_ANGLE, config); } }