예제 #1
0
static void RagdollAddConstraint( IPhysicsEnvironment *pPhysEnv, ragdoll_t &ragdoll, const ragdollparams_t &params, constraint_ragdollparams_t &constraint )
{
	if( constraint.childIndex == constraint.parentIndex )
	{
		DevMsg( 1, "Bogus constraint on ragdoll %s\n", params.pStudioHdr->pszName() );
		constraint.childIndex = -1;
		constraint.parentIndex = -1;
	}
	if ( constraint.childIndex >= 0 && constraint.parentIndex >= 0 )
	{
		Assert(constraint.childIndex<ragdoll.listCount);


		ragdollelement_t &childElement = ragdoll.list[constraint.childIndex];
		// save parent index
		childElement.parentIndex = constraint.parentIndex;

		if ( params.jointFrictionScale > 0 )
		{
			for ( int k = 0; k < 3; k++ )
			{
				constraint.axes[k].torque *= params.jointFrictionScale;
			}
		}
		// this parent/child pair is not usually a parent/child pair in the skeleton.  There
		// are often bones in between that are collapsed for simulation.  So we need to compute
		// the transform.
		Studio_CalcBoneToBoneTransform( params.pStudioHdr, ragdoll.boneIndex[constraint.childIndex], ragdoll.boneIndex[constraint.parentIndex], constraint.constraintToAttached );
		MatrixGetColumn( constraint.constraintToAttached, 3, childElement.originParentSpace );
		// UNDONE: We could transform the constraint limit axes relative to the bone space
		// using this data.  Do we need that feature?
		SetIdentityMatrix( constraint.constraintToReference );
		childElement.pConstraint = pPhysEnv->CreateRagdollConstraint( childElement.pObject, ragdoll.list[constraint.parentIndex].pObject, ragdoll.pGroup, constraint );
	}
}
예제 #2
0
void CStudioPhysics::Load( MDLHandle_t mdlHandle )
{
	m_MDLHandle = mdlHandle;

	LoadPhysicsProperties();

	vcollide_t *pVCollide = GetVCollide( );
	if ( !pVCollide )
	{
		m_pList = NULL;
		m_listCount = 0;
		return;
	}

	m_pList = new CPhysmesh[pVCollide->solidCount];
	m_listCount = pVCollide->solidCount;

	int i;

	for ( i = 0; i < pVCollide->solidCount; i++ )
	{
		m_pList[i].Clear();
		m_pList[i].m_vertCount = physcollision->CreateDebugMesh( pVCollide->solids[i], &m_pList[i].m_pVerts );
		m_pList[i].m_pCollisionModel = physcollision->CreateQueryModel( pVCollide->solids[i] );
	}

	ParseKeydata();

	CStudioHdr studioHdr( g_pMDLCache->GetStudioHdr( mdlHandle ), g_pMDLCache );
	for ( i = 0; i < pVCollide->solidCount; i++ )
	{
		CPhysmesh *pmesh = m_pList + i;
		int boneIndex = FindBoneIndex( &studioHdr, pmesh->m_boneName );
		if ( boneIndex < 0 )
			continue;

		if ( pmesh->m_constraint.parentIndex >= 0 )
		{
			CPhysmesh *pparent = m_pList + pmesh->m_constraint.parentIndex;
			int parentIndex = FindBoneIndex( &studioHdr, pparent->m_boneName );
			Studio_CalcBoneToBoneTransform( &studioHdr, boneIndex, parentIndex, pmesh->m_matrix );
		}
		else
		{
			MatrixInvert( studioHdr.pBone(boneIndex)->poseToBone, pmesh->m_matrix );
		}
	}

	// doesn't have a root bone?  Make it the first bone
	if ( !m_edit.rootName[0] )
	{
		strcpy( m_edit.rootName, m_pList[0].m_boneName );
	}
}
예제 #3
0
Vector GetAttachmentPositionInSpaceOfBone( CStudioHdr *pStudioHdr, const char *pAttachmentName, int outputBoneIndex )
{
	if( !pStudioHdr || !pAttachmentName )
		return vec3_origin;

	int attachment = Studio_FindAttachment( pStudioHdr, pAttachmentName );

	Vector localAttach;
	const mstudioattachment_t &pAttachment = pStudioHdr->pAttachment(attachment);
	int iBone = pStudioHdr->GetAttachmentBone( attachment );
	MatrixGetColumn( pAttachment.local, 3, localAttach );

	matrix3x4_t inputToOutputBone;
	Studio_CalcBoneToBoneTransform( pStudioHdr, iBone, outputBoneIndex, inputToOutputBone );
	
	Vector out;
	VectorTransform( localAttach, inputToOutputBone, out );

	return out;
}
static void RagdollCreateObjects( IPhysicsCollision *pPhysCollision, IPhysicsEnvironment *pPhysEnv, IPhysicsSurfaceProps *pSurfaceDatabase, ragdoll_t &ragdoll, const ragdollparams_t &params )
{
	ragdoll.listCount = 0;
	ragdoll.pGroup = NULL;
	memset( ragdoll.list, 0, sizeof(ragdoll.list) );
	if ( !params.pCollide || params.pCollide->solidCount > RAGDOLL_MAX_ELEMENTS )
		return;

	IVPhysicsKeyParser *pParse = pPhysCollision->VPhysicsKeyParserCreate( params.pCollide->pKeyValues );
	ragdoll.pGroup = pPhysEnv->CreateConstraintGroup();
	while ( !pParse->Finished() )
	{
		const char *pBlock = pParse->GetCurrentBlockName();
		if ( !strcmpi( pBlock, "solid" ) )
		{
			solid_t solid;
			// collisions off by default
			pParse->ParseSolid( &solid, NULL );
			if ( solid.index >= 0 && solid.index < params.pCollide->solidCount)
			{
				Assert( ragdoll.listCount == solid.index );
				int boneIndex = Studio_BoneIndexByName( params.pStudioHdr, solid.name );
				ragdoll.boneIndex[ragdoll.listCount] = boneIndex;

				if ( boneIndex >= 0 )
				{
					solid.params.rotInertiaLimit = 0.5;
					solid.params.pGameData = params.pGameData;
					int surfaceData = pSurfaceDatabase->GetSurfaceIndex( solid.surfaceprop );
					
					if ( surfaceData < 0 )
						surfaceData = pSurfaceDatabase->GetSurfaceIndex( "default" );

					solid.params.pName = params.pStudioHdr->name;
					ragdoll.list[ragdoll.listCount].pObject = pPhysEnv->CreatePolyObject( params.pCollide->solids[solid.index], surfaceData, vec3_origin, vec3_angle, &solid.params );
					ragdoll.list[ragdoll.listCount].pObject->SetPositionMatrix( params.pCurrentBones[boneIndex], true );
					ragdoll.list[ragdoll.listCount].parentIndex = -1;

					ragdoll.listCount++;
				}
				else
				{
					Msg( "CRagdollProp::CreateObjects:  Couldn't Lookup Bone %s\n",
						solid.name );
				}
			}
		}
		else if ( !strcmpi( pBlock, "ragdollconstraint" ) )
		{
			constraint_ragdollparams_t constraint;
			pParse->ParseRagdollConstraint( &constraint, NULL );
			if ( constraint.childIndex >= 0 && constraint.parentIndex >= 0 )
			{
				Assert(constraint.childIndex<ragdoll.listCount);

				ragdollelement_t &childElement = ragdoll.list[constraint.childIndex];
				// save parent index
				childElement.parentIndex = constraint.parentIndex;

				if ( params.jointFrictionScale > 0 )
				{
					for ( int k = 0; k < 3; k++ )
					{
						constraint.axes[k].torque *= params.jointFrictionScale;
					}
				}
				// this parent/child pair is not usually a parent/child pair in the skeleton.  There
				// are often bones in between that are collapsed for simulation.  So we need to compute
				// the transform.
				Studio_CalcBoneToBoneTransform( params.pStudioHdr, ragdoll.boneIndex[constraint.childIndex], ragdoll.boneIndex[constraint.parentIndex], constraint.constraintToAttached );
				MatrixGetColumn( constraint.constraintToAttached, 3, childElement.originParentSpace );
				// UNDONE: We could transform the constraint limit axes relative to the bone space
				// using this data.  Do we need that feature?
				SetIdentityMatrix( constraint.constraintToReference );
				pPhysEnv->DisableCollisions( ragdoll.list[constraint.parentIndex].pObject, childElement.pObject );
				childElement.pConstraint = pPhysEnv->CreateRagdollConstraint( childElement.pObject, ragdoll.list[constraint.parentIndex].pObject, ragdoll.pGroup, constraint );
			}
		}
		else
		{
			pParse->SkipBlock();
		}
	}
	pPhysCollision->VPhysicsKeyParserDestroy( pParse );
}
예제 #5
0
static cache_ragdoll_t *ParseRagdollIntoCache( CStudioHdr *pStudioHdr, vcollide_t *pCollide, int modelIndex )
{
	IVPhysicsKeyParser *pParse = physcollision->VPhysicsKeyParserCreate( pCollide );
	cache_ragdollsolid_t solidList[RAGDOLL_MAX_ELEMENTS];
	cache_ragdollconstraint_t constraintList[RAGDOLL_MAX_ELEMENTS];
	solid_t solid;
	int constraintCount = 0;
	int solidCount = 0;
	cache_ragdoll_t cache;
	V_memset( &cache, 0, sizeof(cache) );
	while ( !pParse->Finished() )
	{
		const char *pBlock = pParse->GetCurrentBlockName();
		if ( !strcmpi( pBlock, "solid" ) )
		{
			pParse->ParseSolid( &solid, &g_SolidSetup );
			cache_ragdollsolid_t *pSolid = &solidList[solidCount];
			pSolid->boneIndex = Studio_BoneIndexByName( pStudioHdr, solid.name );
			if ( pSolid->boneIndex >= 0 )
			{
				pSolid->collideIndex = solid.index;
				pSolid->surfacePropIndex = physprops->GetSurfaceIndex( solid.surfaceprop );
				if ( pSolid->surfacePropIndex < 0 )
				{
					pSolid->surfacePropIndex = physprops->GetSurfaceIndex( "default" );
				}
				pSolid->params = solid.params;
				pSolid->params.enableCollisions = false;
				solidCount++;
			}
			else
			{
				Msg( "ParseRagdollIntoCache:  Couldn't Lookup Bone %s\n", solid.name );
			}
		}
		else if ( !strcmpi( pBlock, "ragdollconstraint" ) )
		{
			constraint_ragdollparams_t constraint;
			pParse->ParseRagdollConstraint( &constraint, NULL );
			if( constraint.childIndex != constraint.parentIndex && constraint.childIndex >= 0 && constraint.parentIndex >= 0)
			{
				cache_ragdollconstraint_t *pOut = &constraintList[constraintCount];
				constraintCount++;
				V_memcpy( pOut->axes, constraint.axes, sizeof(constraint.axes) );
				pOut->parentIndex = constraint.parentIndex;
				pOut->childIndex = constraint.childIndex;
				Studio_CalcBoneToBoneTransform( pStudioHdr, solidList[constraint.childIndex].boneIndex, solidList[constraint.parentIndex].boneIndex, pOut->constraintToAttached );
			}
		}
		else if ( !strcmpi( pBlock, "collisionrules" ) )
		{
			ragdollcollisionrules_t rules;
			IPhysicsCollisionSet *pSet = physics->FindOrCreateCollisionSet( modelIndex, pCollide->solidCount );
			rules.Defaults(physics, pSet);
			pParse->ParseCollisionRules( &rules, NULL );
			cache.pCollisionSet = rules.pCollisionSet;
		}
		else if ( !strcmpi( pBlock, "animatedfriction") ) 
		{
			pParse->ParseRagdollAnimatedFriction( &cache.animfriction, NULL );
		}
		else
		{
			pParse->SkipBlock();
		}
	}
	physcollision->VPhysicsKeyParserDestroy( pParse );
	cache.solidCount = solidCount;
	cache.constraintCount = constraintCount;
	return CreateRagdollCache( pCollide, solidList, constraintList, &cache );
}