// adds all displacement faces as a series of convex objects // UNDONE: Only add the displacements for this model? void Disp_AddCollisionModels( CUtlVector<CPhysCollisionEntry *> &collisionList, dmodel_t *pModel, int contentsMask ) { int dispIndex; // Add each displacement to the grid hash for ( dispIndex = 0; dispIndex < g_CoreDispInfos.Count(); dispIndex++ ) { CCoreDispInfo *pDispInfo = &g_CoreDispInfos[ dispIndex ]; mapdispinfo_t *pMapDisp = &mapdispinfo[ dispIndex ]; // not solid for this pass if ( !(pMapDisp->contents & contentsMask) ) continue; int gridIndex = Disp_GridIndex( pDispInfo ); AddToGrid( gridIndex, dispIndex ); } // now make a polysoup for the terrain in each grid for ( int grid = 0; grid < gDispGridList.Count(); grid++ ) { int triCount = 0; CPhysPolysoup *pTerrainPhysics = physcollision->PolysoupCreate(); // iterate the displacements in this grid for ( int listIndex = 0; listIndex < gDispGridList[grid].dispList.Count(); listIndex++ ) { dispIndex = gDispGridList[grid].dispList[listIndex]; CCoreDispInfo *pDispInfo = &g_CoreDispInfos[ dispIndex ]; mapdispinfo_t *pMapDisp = &mapdispinfo[ dispIndex ]; // Get the material id. MaterialSystemMaterial_t matID = GetMatIDFromDisp( pMapDisp ); // Get the triangle count. int nTriCount = pDispInfo->GetTriCount(); if ( nTriCount >= 0xFFFF ) { // if we hit this error, it's probably time to make the grid adaptive (DISP_GRID_SIZEX,etc) Error("Terrain collision overflow!\n"); } // Convert the tristrip into a triangle list. CUtlVector<unsigned short> indices; indices.SetSize( nTriCount * 3 ); for ( int iTri = 0; iTri < nTriCount; ++iTri ) { unsigned short iVert0, iVert1, iVert2; pDispInfo->GetTriIndices( iTri, iVert0, iVert1, iVert2 ); indices[iTri*3] = iVert0; indices[iTri*3+1] = iVert1; indices[iTri*3+2] = iVert2; } Vector tmpVerts[3]; for ( iTri = 0; iTri < nTriCount; ++iTri ) { float flAlphaTotal = 0.0f; for ( int iTriVert = 0; iTriVert < 3; ++iTriVert ) { pDispInfo->GetVert( indices[iTri*3+iTriVert], tmpVerts[iTriVert] ); flAlphaTotal += pDispInfo->GetAlpha( indices[iTri*3+iTriVert] ); } int nProp = g_SurfaceProperties[texinfo[pMapDisp->face.texinfo].texdata]; if ( flAlphaTotal > DISP_ALPHA_PROP_DELTA ) { int nProp2 = GetSurfaceProperties2( matID, "surfaceprop2" ); if ( nProp2 != -1 ) { nProp = nProp2; } } int nMaterialIndex = RemapWorldMaterial( nProp ); physcollision->PolysoupAddTriangle( pTerrainPhysics, tmpVerts[0], tmpVerts[1], tmpVerts[2], nMaterialIndex ); } } // convert the whole grid's polysoup to a collide and store in the collision list CPhysCollide *pCollide = physcollision->ConvertPolysoupToCollide( pTerrainPhysics ); if ( pCollide ) { collisionList.AddToTail( new CPhysCollisionEntryStaticMesh( pCollide, NULL ) ); } // now that we have the collide, we're done with the soup physcollision->PolysoupDestroy( pTerrainPhysics ); } }
// adds all displacement faces as a series of convex objects // UNDONE: Only add the displacements for this model? void Disp_AddCollisionModels( CUtlVector<CPhysCollisionEntry *> &collisionList, dmodel_t *pModel, int contentsMask) { int dispIndex; // Add each displacement to the grid hash for ( dispIndex = 0; dispIndex < g_CoreDispInfos.Count(); dispIndex++ ) { CCoreDispInfo *pDispInfo = g_CoreDispInfos[ dispIndex ]; mapdispinfo_t *pMapDisp = &mapdispinfo[ dispIndex ]; // not solid for this pass if ( !(pMapDisp->contents & contentsMask) ) continue; int gridIndex = Disp_GridIndex( pDispInfo ); AddToGrid( gridIndex, dispIndex ); } // now make a polysoup for the terrain in each grid for ( int grid = 0; grid < gDispGridList.Count(); grid++ ) { int triCount = 0; CPhysPolysoup *pTerrainPhysics = physcollision->PolysoupCreate(); // iterate the displacements in this grid for ( int listIndex = 0; listIndex < gDispGridList[grid].dispList.Count(); listIndex++ ) { dispIndex = gDispGridList[grid].dispList[listIndex]; CCoreDispInfo *pDispInfo = g_CoreDispInfos[ dispIndex ]; mapdispinfo_t *pMapDisp = &mapdispinfo[ dispIndex ]; // Get the material id. MaterialSystemMaterial_t matID = GetMatIDFromDisp( pMapDisp ); // Build a triangle list. This shares the tesselation code with the engine. CUtlVector<unsigned short> indices; CVBSPTesselateHelper helper; helper.m_pIndices = &indices; helper.m_pActiveVerts = pDispInfo->GetAllowedVerts().Base(); helper.m_pPowerInfo = pDispInfo->GetPowerInfo(); ::TesselateDisplacement( &helper ); Assert( indices.Count() > 0 ); Assert( indices.Count() % 3 == 0 ); // Make sure indices are a multiple of 3. int nTriCount = indices.Count() / 3; triCount += nTriCount; if ( triCount >= 65536 ) { // don't put more than 64K tris in any single collision model CPhysCollide *pCollide = physcollision->ConvertPolysoupToCollide( pTerrainPhysics, false ); if ( pCollide ) { collisionList.AddToTail( new CPhysCollisionEntryStaticMesh( pCollide, NULL ) ); } // Throw this polysoup away and start over for the remaining triangles physcollision->PolysoupDestroy( pTerrainPhysics ); pTerrainPhysics = physcollision->PolysoupCreate(); triCount = nTriCount; } Vector tmpVerts[3]; for ( int iTri = 0; iTri < nTriCount; ++iTri ) { float flAlphaTotal = 0.0f; for ( int iTriVert = 0; iTriVert < 3; ++iTriVert ) { pDispInfo->GetVert( indices[iTri*3+iTriVert], tmpVerts[iTriVert] ); flAlphaTotal += pDispInfo->GetAlpha( indices[iTri*3+iTriVert] ); } int nProp = g_SurfaceProperties[texinfo[pMapDisp->face.texinfo].texdata]; if ( flAlphaTotal > DISP_ALPHA_PROP_DELTA ) { int nProp2 = GetSurfaceProperties2( matID, "surfaceprop2" ); if ( nProp2 != -1 ) { nProp = nProp2; } } int nMaterialIndex = RemapWorldMaterial( nProp ); physcollision->PolysoupAddTriangle( pTerrainPhysics, tmpVerts[0], tmpVerts[1], tmpVerts[2], nMaterialIndex ); } } // convert the whole grid's polysoup to a collide and store in the collision list CPhysCollide *pCollide = physcollision->ConvertPolysoupToCollide( pTerrainPhysics, false ); if ( pCollide ) { collisionList.AddToTail( new CPhysCollisionEntryStaticMesh( pCollide, NULL ) ); } // now that we have the collide, we're done with the soup physcollision->PolysoupDestroy( pTerrainPhysics ); } }