//----------------------------------------------------------------------------- // Purpose: Parses the vehicle's script for the vehicle view parameters //----------------------------------------------------------------------------- bool CPropVehicleChoreoGeneric::ParseViewParams( const char *pScriptName ) { byte *pFile = UTIL_LoadFileForMe( pScriptName, NULL ); if ( !pFile ) return false; IVPhysicsKeyParser *pParse = physcollision->VPhysicsKeyParserCreate( (char *)pFile ); CVehicleChoreoViewParser viewParser; while ( !pParse->Finished() ) { const char *pBlock = pParse->GetCurrentBlockName(); if ( !strcmpi( pBlock, "vehicle_view" ) ) { pParse->ParseCustom( &m_vehicleView, &viewParser ); } else { pParse->SkipBlock(); } } physcollision->VPhysicsKeyParserDestroy( pParse ); UTIL_FreeFile( pFile ); Precache(); return true; }
//----------------------------------------------------------------------------- // Purpose: // Input : modelindex - //----------------------------------------------------------------------------- void PrecachePropsForModel( int iModel, const char *pszBlockName ) { vcollide_t *pCollide = modelinfo->GetVCollide( iModel ); if ( !pCollide ) return; // The scale and group doesn't really matter at the moment, we are just using the parser to get the model name to cache. CBreakParser breakParser( 1.0, COLLISION_GROUP_NONE ); // Create a parser. IVPhysicsKeyParser *pParse = physcollision->VPhysicsKeyParserCreate( pCollide->pKeyValues ); while ( !pParse->Finished() ) { const char *pBlock = pParse->GetCurrentBlockName(); if ( !strcmpi( pBlock, pszBlockName ) ) { breakmodel_t breakModel; pParse->ParseCustom( &breakModel, &breakParser ); CBaseEntity::PrecacheModel( breakModel.modelName ); } else { pParse->SkipBlock(); } } // Destroy the parser. physcollision->VPhysicsKeyParserDestroy( pParse ); }
void BuildPropList( const char *pszBlockName, CUtlVector<breakmodel_t> &list, int modelindex, float defBurstScale, int defCollisionGroup ) { vcollide_t *pCollide = modelinfo->GetVCollide( modelindex ); if ( !pCollide ) return; IVPhysicsKeyParser *pParse = physcollision->VPhysicsKeyParserCreate( pCollide->pKeyValues ); while ( !pParse->Finished() ) { CBreakParser breakParser( defBurstScale, defCollisionGroup ); const char *pBlock = pParse->GetCurrentBlockName(); if ( !strcmpi( pBlock, pszBlockName ) ) { int index = list.AddToTail(); breakmodel_t &breakModel = list[index]; pParse->ParseCustom( &breakModel, &breakParser ); } else { pParse->SkipBlock(); } } physcollision->VPhysicsKeyParserDestroy( pParse ); }
void RagdollSetupAnimatedFriction( IPhysicsEnvironment *pPhysEnv, ragdoll_t *ragdoll, int iModelIndex ) { vcollide_t* pCollide = modelinfo->GetVCollide( iModelIndex ); if ( pCollide ) { IVPhysicsKeyParser *pParse = physcollision->VPhysicsKeyParserCreate( pCollide->pKeyValues ); while ( !pParse->Finished() ) { const char *pBlock = pParse->GetCurrentBlockName(); if ( !strcmpi( pBlock, "animatedfriction") ) { CRagdollAnimatedFriction friction( ragdoll ); pParse->ParseCustom( (void*)&friction, &friction ); } else { pParse->SkipBlock(); } } physcollision->VPhysicsKeyParserDestroy( pParse ); } }
// Parse the ragdoll and obtain the mapping from each physics element index to a bone index // returns num phys elements int RagdollExtractBoneIndices( int *boneIndexOut, studiohdr_t *pStudioHdr, vcollide_t *pCollide ) { int elementCount = 0; IVPhysicsKeyParser *pParse = physcollision->VPhysicsKeyParserCreate( pCollide->pKeyValues ); while ( !pParse->Finished() ) { const char *pBlock = pParse->GetCurrentBlockName(); if ( !strcmpi( pBlock, "solid" ) ) { solid_t solid; pParse->ParseSolid( &solid, NULL ); if ( solid.index >= 0 && solid.index < pCollide->solidCount) { if ( elementCount < RAGDOLL_MAX_ELEMENTS ) { boneIndexOut[elementCount] = Studio_BoneIndexByName( pStudioHdr, solid.name ); elementCount++; } } } else { pParse->SkipBlock(); } } physcollision->VPhysicsKeyParserDestroy( pParse ); return elementCount; }
//----------------------------------------------------------------------------- // Create VPhysics representation //----------------------------------------------------------------------------- void CStaticProp::CreateVPhysics( IPhysicsEnvironment *pPhysEnv, IVPhysicsKeyHandler *pDefaults, void *pGameData ) { if ( m_nSolidType == SOLID_NONE ) return; vcollide_t temp; solid_t solid; CPhysCollide* pTempStorage; vcollide_t *pVCollide = NULL; if ( m_pModel && m_nSolidType == SOLID_VPHYSICS ) { // This works because VCollideForModel only uses modelindex for mod_brush // and props are always mod_Studio. pVCollide = CM_VCollideForModel( -1, m_pModel ); } // If there's no collide, we need a bbox... if (!pVCollide) { temp.solidCount = 1; temp.pKeyValues = ""; temp.solids = &pTempStorage; temp.solids[0] = physcollision->BBoxToCollide( m_pModel->mins, m_pModel->maxs ); if (!temp.solids[0]) return; pVCollide = &temp; solid.params = g_PhysDefaultObjectParams; } else { IVPhysicsKeyParser *pParse = physcollision->VPhysicsKeyParserCreate( pVCollide->pKeyValues ); while ( !pParse->Finished() ) { const char *pBlock = pParse->GetCurrentBlockName(); if ( !strcmpi( pBlock, "solid" ) ) { pParse->ParseSolid( &solid, pDefaults ); break; } else { pParse->SkipBlock(); } } physcollision->VPhysicsKeyParserDestroy( pParse ); } solid.params.enableCollisions = true; solid.params.pGameData = pGameData; solid.params.pName = "prop_static"; int surfaceData = physprop->GetSurfaceIndex( solid.surfaceprop ); pPhysEnv->CreatePolyObjectStatic( pVCollide->solids[0], surfaceData, m_Origin, m_Angles, &solid.params ); //PhysCheckAdd( pPhys, "Static" ); }
void RagdollSetupCollisions( ragdoll_t &ragdoll, vcollide_t *pCollide, int modelIndex ) { Assert(pCollide); if (!pCollide) return; IPhysicsCollisionSet *pSet = physics->FindCollisionSet( modelIndex ); if ( !pSet ) { pSet = physics->FindOrCreateCollisionSet( modelIndex, pCollide->solidCount ); if ( !pSet ) return; bool bFoundRules = false; IVPhysicsKeyParser *pParse = physcollision->VPhysicsKeyParserCreate( pCollide ); while ( !pParse->Finished() ) { const char *pBlock = pParse->GetCurrentBlockName(); if ( !strcmpi( pBlock, "collisionrules" ) ) { ragdollcollisionrules_t rules; rules.Defaults(physics, pSet); pParse->ParseCollisionRules( &rules, NULL ); Assert(rules.pCollisionSet == pSet); bFoundRules = true; } else { pParse->SkipBlock(); } } physcollision->VPhysicsKeyParserDestroy( pParse ); if ( !bFoundRules ) { // these are the default rules - each piece collides with everything // except immediate parent/constrained object. int i; for ( i = 0; i < ragdoll.listCount; i++ ) { for ( int j = i+1; j < ragdoll.listCount; j++ ) { pSet->EnableCollisions( i, j ); } } for ( i = 0; i < ragdoll.listCount; i++ ) { int parent = ragdoll.list[i].parentIndex; if ( parent >= 0 ) { Assert( ragdoll.list[i].pObject ); Assert( ragdoll.list[i].pConstraint ); pSet->DisableCollisions( i, parent ); } } } } }
//----------------------------------------------------------------------------- // Purpose: // Input : &solid - // *pEntity - // modelIndex - // solidIndex - // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- bool PhysModelParseSolidByIndex( solid_t &solid, CBaseEntity *pEntity, int modelIndex, int solidIndex ) { vcollide_t *pCollide = modelinfo->GetVCollide( modelIndex ); if ( !pCollide ) return false; bool parsed = false; memset( &solid, 0, sizeof(solid) ); solid.params = g_PhysDefaultObjectParams; #if !defined(USE_PHX_FILES) IVPhysicsKeyParser *pParse = physcollision->VPhysicsKeyParserCreate( pCollide->pKeyValues ); while ( !pParse->Finished() ) { const char *pBlock = pParse->GetCurrentBlockName(); if ( !strcmpi( pBlock, "solid" ) ) { solid_t tmpSolid; memset( &tmpSolid, 0, sizeof(tmpSolid) ); tmpSolid.params = g_PhysDefaultObjectParams; pParse->ParseSolid( &tmpSolid, &g_SolidSetup ); if ( solidIndex < 0 || tmpSolid.index == solidIndex ) { parsed = true; solid = tmpSolid; // just to be sure we aren't ever getting a non-zero solid by accident Assert( solidIndex >= 0 || solid.index == 0 ); break; } } else { pParse->SkipBlock(); } } physcollision->VPhysicsKeyParserDestroy( pParse ); #else Assert( pCollide->isPacked ); CPackedPhysicsDescription *pPacked = physcollision->CreatePackedDesc( pCollide->pKeyValues, pCollide->descSize ); if ( solidIndex < 0 ) // -1 means first solid solidIndex = 0; pPacked->GetSolid( &solid, solidIndex ); physcollision->DestroyPackedDesc( pPacked ); parsed = true; #endif // collisions are off by default solid.params.enableCollisions = true; solid.params.pGameData = static_cast<void *>(pEntity); solid.params.pName = STRING(pEntity->GetModelName()); return parsed; }
//----------------------------------------------------------------------------- // Purpose: Parses the vehicle's script //----------------------------------------------------------------------------- bool CFourWheelVehiclePhysics::ParseVehicleScript( const char *pScriptName, solid_t &solid, vehicleparams_t &vehicle) { byte *pFile = UTIL_LoadFileForMe( pScriptName, NULL ); if ( !pFile ) return false; IVPhysicsKeyParser *pParse = physcollision->VPhysicsKeyParserCreate( (char *)pFile ); while ( !pParse->Finished() ) { const char *pBlock = pParse->GetCurrentBlockName(); if ( !strcmpi( pBlock, "vehicle" ) ) { pParse->ParseVehicle( &vehicle, NULL ); } else { pParse->SkipBlock(); } } physcollision->VPhysicsKeyParserDestroy( pParse ); UTIL_FreeFile( pFile ); m_debugRadius = vehicle.axles[0].wheels.radius; CalcWheelData( vehicle ); PhysModelParseSolid( solid, m_pOuter, m_pOuter->GetModelIndex() ); // Allow the script to shift the center of mass if ( vehicle.body.massCenterOverride != vec3_origin ) { solid.massCenterOverride = vehicle.body.massCenterOverride; solid.params.massCenterOverride = &solid.massCenterOverride; } // allow script to change the mass of the vehicle body if ( vehicle.body.massOverride > 0 ) { solid.params.mass = vehicle.body.massOverride; } return true; }
//----------------------------------------------------------------------------- // Purpose: // Input : &solid - // *pEntity - // *pCollide - // solidIndex - // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- bool PhysModelParseSolidByIndex( solid_t &solid, CBaseEntity *pEntity, vcollide_t *pCollide, int solidIndex ) { bool parsed = false; memset( &solid, 0, sizeof(solid) ); solid.params = g_PhysDefaultObjectParams; IVPhysicsKeyParser *pParse = physcollision->VPhysicsKeyParserCreate( pCollide ); while ( !pParse->Finished() ) { const char *pBlock = pParse->GetCurrentBlockName(); if ( !strcmpi( pBlock, "solid" ) ) { solid_t tmpSolid; memset( &tmpSolid, 0, sizeof(tmpSolid) ); tmpSolid.params = g_PhysDefaultObjectParams; pParse->ParseSolid( &tmpSolid, &g_SolidSetup ); if ( solidIndex < 0 || tmpSolid.index == solidIndex ) { parsed = true; solid = tmpSolid; // just to be sure we aren't ever getting a non-zero solid by accident Assert( solidIndex >= 0 || solid.index == 0 ); break; } } else { pParse->SkipBlock(); } } physcollision->VPhysicsKeyParserDestroy( pParse ); // collisions are off by default solid.params.enableCollisions = true; solid.params.pGameData = static_cast<void *>(pEntity); solid.params.pName = STRING(pEntity->GetModelName()); return parsed; }
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 ); }
IPhysicsObject *PhysModelCreateRagdoll( C_BaseEntity *pEntity, int modelIndex, const Vector &origin, const QAngle &angles ) { vcollide_t *pCollide = modelinfo->GetVCollide( modelIndex ); if ( !pCollide ) return NULL; solid_t solid; memset( &solid, 0, sizeof(solid) ); solid.params = g_PhysDefaultObjectParams; IVPhysicsKeyParser *pParse = physcollision->VPhysicsKeyParserCreate( pCollide->pKeyValues ); while ( !pParse->Finished() ) { const char *pBlock = pParse->GetCurrentBlockName(); if ( !strcmpi( pBlock, "solid" ) ) { pParse->ParseSolid( &solid, &g_SolidSetup ); break; } else { pParse->SkipBlock(); } } physcollision->VPhysicsKeyParserDestroy( pParse ); // collisions are off by default solid.params.enableCollisions = true; int surfaceProp = -1; if ( solid.surfaceprop[0] ) { surfaceProp = physprops->GetSurfaceIndex( solid.surfaceprop ); } solid.params.pGameData = static_cast<void *>(pEntity); solid.params.pName = "ragdoll_player"; IPhysicsObject *pObject = physenv->CreatePolyObject( pCollide->solids[0], surfaceProp, origin, angles, &solid.params ); //PhysCheckAdd( pObject, STRING(pEntity->m_iClassname) ); return pObject; }
// create a manager and a list of followers directly from a ragdoll void CreateBoneFollowersFromRagdoll( CBaseAnimating *pEntity, CBoneFollowerManager *pManager, vcollide_t *pCollide ) { IVPhysicsKeyParser *pParse = physcollision->VPhysicsKeyParserCreate( pCollide->pKeyValues ); while ( !pParse->Finished() ) { const char *pBlock = pParse->GetCurrentBlockName(); if ( !strcmpi( pBlock, "solid" ) ) { solid_t solid; pParse->ParseSolid( &solid, NULL ); // collisions are off by default, turn them on solid.params.enableCollisions = true; solid.params.pName = STRING(pEntity->GetModelName()); pManager->AddBoneFollower( pEntity, solid.name, &solid ); } else { pParse->SkipBlock(); } } }
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 ); }
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 ); }
IPhysicsObject *PhysCreateWorld_Shared( CBaseEntity *pWorld, vcollide_t *pWorldCollide, const objectparams_t &defaultParams ) { solid_t solid; fluid_t fluid; int surfaceData = physprops->GetSurfaceIndex( "default" ); objectparams_t params = defaultParams; params.pGameData = static_cast<void *>(pWorld); params.pName = "world"; IPhysicsObject *pWorldPhysics = physenv->CreatePolyObjectStatic( pWorldCollide->solids[0], surfaceData, vec3_origin, vec3_angle, ¶ms ); // hint - saves vphysics some work pWorldPhysics->SetCallbackFlags( pWorldPhysics->GetCallbackFlags() | CALLBACK_NEVER_DELETED ); //PhysCheckAdd( world, "World" ); // walk the world keys in case there are some fluid volumes to create IVPhysicsKeyParser *pParse = physcollision->VPhysicsKeyParserCreate( pWorldCollide ); bool bCreateVirtualTerrain = false; while ( !pParse->Finished() ) { const char *pBlock = pParse->GetCurrentBlockName(); if ( !strcmpi( pBlock, "solid" ) || !strcmpi( pBlock, "staticsolid" ) ) { solid.params = defaultParams; pParse->ParseSolid( &solid, &g_SolidSetup ); solid.params.enableCollisions = true; solid.params.pGameData = static_cast<void *>(pWorld); solid.params.pName = "world"; int surfaceData = physprops->GetSurfaceIndex( "default" ); // already created world above if ( solid.index == 0 ) continue; if ( !pWorldCollide->solids[solid.index] ) { // this implies that the collision model is a mopp and the physics DLL doesn't support that. bCreateVirtualTerrain = true; continue; } // create this as part of the world IPhysicsObject *pObject = physenv->CreatePolyObjectStatic( pWorldCollide->solids[solid.index], surfaceData, vec3_origin, vec3_angle, &solid.params ); // invalid collision model or can't create, ignore if (!pObject) continue; pObject->SetCallbackFlags( pObject->GetCallbackFlags() | CALLBACK_NEVER_DELETED ); Assert( solid.contents != 0 ); pObject->SetContents( solid.contents ); if ( solid.contents & CONTENTS_SOLID ) { pObject->SetCollisionHints(COLLISION_HINT_STATICSOLID); } if ( !pWorldPhysics ) { pWorldPhysics = pObject; } } else if ( !strcmpi( pBlock, "fluid" ) ) { pParse->ParseFluid( &fluid, NULL ); // create a fluid for floating if ( fluid.index > 0 ) { solid.params = defaultParams; // copy world's params solid.params.enableCollisions = true; solid.params.pName = "fluid"; solid.params.pGameData = static_cast<void *>(pWorld); fluid.params.pGameData = static_cast<void *>(pWorld); int surfaceData = physprops->GetSurfaceIndex( fluid.surfaceprop ); // create this as part of the world IPhysicsObject *pWater = physenv->CreatePolyObjectStatic( pWorldCollide->solids[fluid.index], surfaceData, vec3_origin, vec3_angle, &solid.params ); pWater->SetCallbackFlags( pWater->GetCallbackFlags() | CALLBACK_NEVER_DELETED ); physenv->CreateFluidController( pWater, &fluid.params ); } } else if ( !strcmpi( pBlock, "materialtable" ) ) { int surfaceTable[128]; memset( surfaceTable, 0, sizeof(surfaceTable) ); pParse->ParseSurfaceTable( surfaceTable, NULL ); physprops->SetWorldMaterialIndexTable( surfaceTable, 128 ); } else if ( !strcmpi(pBlock, "virtualterrain" ) ) { bCreateVirtualTerrain = true; pParse->SkipBlock(); } else { // unknown chunk??? pParse->SkipBlock(); } } physcollision->VPhysicsKeyParserDestroy( pParse ); if ( bCreateVirtualTerrain && physcollision->SupportsVirtualMesh() ) { PhysCreateVirtualTerrain( pWorld, defaultParams ); } return pWorldPhysics; }
void CMDLPanel::DrawCollisionModel() { vcollide_t *pCollide = MDLCache()->GetVCollide( m_hMDL->GetMDL() ); if ( !pCollide || pCollide->solidCount <= 0 ) return; static color32 color = {255,0,0,0}; IVPhysicsKeyParser *pParser = g_pPhysicsCollision->VPhysicsKeyParserCreate( pCollide->pKeyValues ); CStudioHdr studioHdr( g_pMDLCache->GetStudioHdr( m_hMDL->GetMDL() ), g_pMDLCache ); matrix3x4_t pBoneToWorld[MAXSTUDIOBONES]; matrix3x4_t shapeToWorld; m_pDag->GetTransform()->GetTransform( shapeToWorld ); m_hMDL->SetUpBones( shapeToWorld, MAXSTUDIOBONES, pBoneToWorld ); // PERFORMANCE: Just parse the script each frame. It's fast enough for tools. If you need // this to go faster then cache off the bone index mapping in an array like HLMV does while ( !pParser->Finished() ) { const char *pBlock = pParser->GetCurrentBlockName(); if ( !stricmp( pBlock, "solid" ) ) { solid_t solid; pParser->ParseSolid( &solid, NULL ); int boneIndex = Studio_BoneIndexByName( &studioHdr, solid.name ); Vector *outVerts; int vertCount = g_pPhysicsCollision->CreateDebugMesh( pCollide->solids[solid.index], &outVerts ); if ( vertCount ) { CMatRenderContextPtr pRenderContext( g_pMaterialSystem ); pRenderContext->CullMode( MATERIAL_CULLMODE_CCW ); // NOTE: assumes these have been set up already by the model render code // So this is a little bit of a back door to a cache of the bones // this code wouldn't work unless you draw the model this frame before calling // this routine. CMDLPanel always does this, but it's worth noting. // A better solution would be to move the ragdoll visulization into the CDmeMdl // and either draw it there or make it queryable and query/draw here. matrix3x4_t xform; SetIdentityMatrix( xform ); if ( boneIndex >= 0 ) { MatrixCopy( pBoneToWorld[ boneIndex ], xform ); } IMesh *pMesh = pRenderContext->GetDynamicMesh( true, NULL, NULL, m_Wireframe ); CMeshBuilder meshBuilder; meshBuilder.Begin( pMesh, MATERIAL_TRIANGLES, vertCount/3 ); for ( int j = 0; j < vertCount; j++ ) { Vector out; VectorTransform( outVerts[j].Base(), xform, out.Base() ); meshBuilder.Position3fv( out.Base() ); meshBuilder.Color4ub( color.r, color.g, color.b, color.a ); meshBuilder.TexCoord2f( 0, 0, 0 ); meshBuilder.AdvanceVertex(); } meshBuilder.End(); pMesh->Draw(); } g_pPhysicsCollision->DestroyDebugMesh( vertCount, outVerts ); } else { pParser->SkipBlock(); } } g_pPhysicsCollision->VPhysicsKeyParserDestroy( pParser ); }