bool 
Character::getFramePose(PxTransform &rootTransform, SampleArray<PxVec3> &positions, SampleArray<PxU32> &indexBuffers)
{
	if (mCurrentMotion == NULL)
		return false;

	PxU32 frameNo = PxU32(mFrameTime);
	if (frameNo >= mCurrentMotion->mNbFrames)
		return false;

	positions.resize(mNbBones+1);

	// copy precomputed bone position in local space
	positions[0] = PxVec3(0.0f); // root position
	for (PxU32 i = 0; i < mNbBones; i++)
		positions[i+1] = mCurrentBoneTransform[i].p;

	// copy capsule index data
	indexBuffers.resize(mASFData->mNbBones * 2);
	for (PxU32 i = 0; i < mASFData->mNbBones; i++)
	{
		Acclaim::Bone& bone = mASFData->mBones[i];
		indexBuffers[i*2] = bone.mID;
		indexBuffers[i*2+1] = (bone.mParent) ? bone.mParent->mID : 0;
	}

	// compute root transform
	rootTransform = mCharacterPose.transform(mCurrentRootTransform);

	return true;
}
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();
}
Beispiel #3
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;
}
Beispiel #4
0
void Test::TestGroup::getPath(SampleArray<TestGroup*>& path)
{
	if (getParent())
		getParent()->getPath(path);

	path.pushBack(this);
}
/*----------------------------------------------------------------------
|   TrackCursor::SetSampleIndex
+---------------------------------------------------------------------*/
AP4_Result
TrackCursor::SetSampleIndex(AP4_Ordinal sample_index)
{
    m_SampleIndex = sample_index;
    
    // check if we're at the end
    if (sample_index >= m_Samples->GetSampleCount()) {
        AP4_UI64 end_dts = m_Sample.GetDts()+m_Sample.GetDuration();
        m_Sample.Reset();
        m_Sample.SetDts(end_dts);
        m_Eos = true;
    } else {
        return m_Samples->GetSample(m_SampleIndex, m_Sample);
    }
    
    return AP4_SUCCESS;
}
Beispiel #6
0
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::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::computeNewPositions(Character &character, SampleArray<PxVec3> &particlePositions)
{
	if (character.mCurrentMotion == NULL)
		return false;

	PxTransform t = character.mCurrentBoneTransform[mBoneID];
	particlePositions.resize(mBindPos.size());

	for (PxU32 i = 0; i < mBindPos.size(); i++)
		particlePositions[i] = t.transform(mBindPos[i]);

	return true;
}
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;
}
/*----------------------------------------------------------------------
|   TrackCursor::Init
+---------------------------------------------------------------------*/
AP4_Result
TrackCursor::Init()
{
    return m_Samples->GetSample(0, m_Sample);
}
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);
	}
}