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();
}
Exemplo n.º 2
0
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);
	}
}
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);
	}
}