void CStudioPhysics::ParseKeydata( void ) { IVPhysicsKeyParser *pParser = physcollision->VPhysicsKeyParserCreate( GetVCollide()->pKeyValues ); while ( !pParser->Finished() ) { const char *pBlock = pParser->GetCurrentBlockName(); if ( !stricmp( pBlock, "solid" ) ) { hlmvsolid_t solid; CSolidParse solidParse; pParser->ParseSolid( &solid, &solidParse ); solid.surfacePropIndex = FindPhysprop( solid.surfaceprop ); if ( solid.index >= 0 && solid.index < m_listCount ) { strcpy( m_pList[solid.index].m_boneName, solid.name ); memcpy( &m_pList[solid.index].m_solid, &solid, sizeof(solid) ); } } else if ( !stricmp( pBlock, "ragdollconstraint" ) ) { constraint_ragdollparams_t constraint; pParser->ParseRagdollConstraint( &constraint, NULL ); if ( constraint.childIndex >= 0 && constraint.childIndex < m_listCount ) { // In the editor / qc these show up as 5X so that 1.0 is the default constraint.axes[0].torque *= 5; constraint.axes[1].torque *= 5; constraint.axes[2].torque *= 5; m_pList[constraint.childIndex].m_constraint = constraint; } } else if ( !stricmp( pBlock, "editparams" ) ) { CEditParse editParse; pParser->ParseCustom( &m_edit, &editParse ); m_mass = m_edit.totalMass; } else if ( !strcmpi( pBlock, "collisionrules" ) ) { CRagdollCollisionRulesParse rules(this); pParser->ParseCustom( NULL, &rules ); } else { pParser->SkipBlock(); } } physcollision->VPhysicsKeyParserDestroy( pParser ); }
static void RagdollCreateObjects( IPhysicsEnvironment *pPhysEnv, ragdoll_t &ragdoll, const ragdollparams_t ¶ms ) { ragdoll.listCount = 0; ragdoll.pGroup = NULL; ragdoll.allowStretch = params.allowStretch; memset( ragdoll.list, 0, sizeof(ragdoll.list) ); memset( &ragdoll.animfriction, 0, sizeof(ragdoll.animfriction) ); if ( !params.pCollide || params.pCollide->solidCount > RAGDOLL_MAX_ELEMENTS ) return; constraint_groupparams_t group; group.Defaults(); ragdoll.pGroup = pPhysEnv->CreateConstraintGroup( group ); IVPhysicsKeyParser *pParse = physcollision->VPhysicsKeyParserCreate( params.pCollide->pKeyValues ); while ( !pParse->Finished() ) { const char *pBlock = pParse->GetCurrentBlockName(); if ( !strcmpi( pBlock, "solid" ) ) { solid_t solid; pParse->ParseSolid( &solid, &g_SolidSetup ); RagdollAddSolid( pPhysEnv, ragdoll, params, solid ); } else if ( !strcmpi( pBlock, "ragdollconstraint" ) ) { constraint_ragdollparams_t constraint; pParse->ParseRagdollConstraint( &constraint, NULL ); RagdollAddConstraint( pPhysEnv, ragdoll, params, constraint ); } else if ( !strcmpi( pBlock, "collisionrules" ) ) { IPhysicsCollisionSet *pSet = physics->FindOrCreateCollisionSet( params.modelIndex, ragdoll.listCount ); CRagdollCollisionRules rules(pSet); pParse->ParseCustom( (void *)&rules, &rules ); } else if ( !strcmpi( pBlock, "animatedfriction") ) { CRagdollAnimatedFriction friction( &ragdoll ); pParse->ParseCustom( (void*)&friction, &friction ); } else { pParse->SkipBlock(); } } physcollision->VPhysicsKeyParserDestroy( pParse ); }
static void RagdollCreateObjects( IPhysicsCollision *pPhysCollision, IPhysicsEnvironment *pPhysEnv, IPhysicsSurfaceProps *pSurfaceDatabase, ragdoll_t &ragdoll, const ragdollparams_t ¶ms ) { 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 ); }
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 ); }