//----------------------------------------------------------------------------- // Computes a convex hull from a studio mesh //----------------------------------------------------------------------------- static void AddMeshToPolysoup( CPhysPolysoup* pSoup, mstudiomesh_t* pMesh, OptimizedModel::MeshHeader_t* pVtxMesh ) { Vector v[3]; for (int i = 0; i < pVtxMesh->numStripGroups; ++i ) { OptimizedModel::StripGroupHeader_t* pStripGroup = pVtxMesh->pStripGroup(i); if (pStripGroup->flags & OptimizedModel::STRIP_IS_TRILIST) { for (int j = 0; j < pStripGroup->numStrips; ++j ) { OptimizedModel::StripHeader_t* pStrip = pStripGroup->pStrip(i); int numTri = pStrip->numIndices / 3; unsigned short* pIdx = pStripGroup->pIndex(pStrip->indexOffset); for (int k = 0; k < numTri; ++k) { v[0] = *PositionFromIndex( pMesh, pStripGroup, pIdx[3*k] ); v[1] = *PositionFromIndex( pMesh, pStripGroup, pIdx[3*k+1] ); v[2] = *PositionFromIndex( pMesh, pStripGroup, pIdx[3*k+2] ); s_pPhysCollision->PolysoupAddTriangle( pSoup, v[0], v[1], v[2], 0 ); } } } else { for (int j = 0; j < pStripGroup->numStrips; ++j ) { OptimizedModel::StripHeader_t* pStrip = pStripGroup->pStrip(i); int numTri = pStrip->numIndices - 2; unsigned short* pIdx = pStripGroup->pIndex(pStrip->indexOffset); for (int k = 0; k < numTri; ++k) { v[0] = *PositionFromIndex( pMesh, pStripGroup, pIdx[k] ); bool winding = ( (k & 0x1) == 0 ); v[2 - winding] = *PositionFromIndex( pMesh, pStripGroup, pIdx[k+1] ); v[1 + winding] = *PositionFromIndex( pMesh, pStripGroup, pIdx[k+2] ); s_pPhysCollision->PolysoupAddTriangle( pSoup, v[0], v[1], v[2], 0 ); } } } } }
//----------------------------------------------------------------------------- // Adds all static prop polys to the ray trace store. //----------------------------------------------------------------------------- void CVradStaticPropMgr::AddPolysForRayTrace( void ) { int count = m_StaticProps.Count(); if ( !count ) { // nothing to do return; } for ( int nProp = 0; nProp < count; ++nProp ) { CStaticProp &prop = m_StaticProps[nProp]; if ( prop.m_Flags & STATIC_PROP_NO_SHADOW ) continue; StaticPropDict_t &dict = m_StaticPropDict[prop.m_ModelIdx]; studiohdr_t *pStudioHdr = dict.m_pStudioHdr; OptimizedModel::FileHeader_t *pVtxHdr = (OptimizedModel::FileHeader_t *)dict.m_VtxBuf.Base(); if ( !pStudioHdr || !pVtxHdr ) { // must have model and its verts for decoding triangles return; } // for access to this model's vertexes SetCurrentModel( pStudioHdr ); // meshes are deeply hierarchial, divided between three stores, follow the white rabbit // body parts -> models -> lod meshes -> strip groups -> strips // the vertices and indices are pooled, the trick is knowing the offset to determine your indexed base for ( int bodyID = 0; bodyID < pStudioHdr->numbodyparts; ++bodyID ) { OptimizedModel::BodyPartHeader_t* pVtxBodyPart = pVtxHdr->pBodyPart( bodyID ); mstudiobodyparts_t *pBodyPart = pStudioHdr->pBodypart( bodyID ); for ( int modelID = 0; modelID < pBodyPart->nummodels; ++modelID ) { OptimizedModel::ModelHeader_t* pVtxModel = pVtxBodyPart->pModel( modelID ); mstudiomodel_t *pStudioModel = pBodyPart->pModel( modelID ); // assuming lod 0, could iterate if required int nLod = 0; OptimizedModel::ModelLODHeader_t *pVtxLOD = pVtxModel->pLOD( nLod ); for ( int nMesh = 0; nMesh < pStudioModel->nummeshes; ++nMesh ) { mstudiomesh_t* pMesh = pStudioModel->pMesh( nMesh ); OptimizedModel::MeshHeader_t* pVtxMesh = pVtxLOD->pMesh( nMesh ); const mstudio_meshvertexdata_t *vertData = pMesh->GetVertexData(); for ( int nGroup = 0; nGroup < pVtxMesh->numStripGroups; ++nGroup ) { OptimizedModel::StripGroupHeader_t* pStripGroup = pVtxMesh->pStripGroup( nGroup ); int nStrip; for ( nStrip = 0; nStrip < pStripGroup->numStrips; nStrip++ ) { OptimizedModel::StripHeader_t *pStrip = pStripGroup->pStrip( nStrip ); if ( pStrip->flags & OptimizedModel::STRIP_IS_TRILIST ) { for ( int i = 0; i < pStrip->numIndices; i += 3 ) { int idx = pStrip->indexOffset + i; unsigned short i1 = *pStripGroup->pIndex( idx ); unsigned short i2 = *pStripGroup->pIndex( idx + 1 ); unsigned short i3 = *pStripGroup->pIndex( idx + 2 ); int vertex1 = pStripGroup->pVertex( i1 )->origMeshVertID; int vertex2 = pStripGroup->pVertex( i2 )->origMeshVertID; int vertex3 = pStripGroup->pVertex( i3 )->origMeshVertID; // transform position into world coordinate system matrix3x4_t matrix; AngleMatrix( prop.m_Angles, prop.m_Origin, matrix ); Vector position1; Vector position2; Vector position3; VectorTransform( *vertData->Position( vertex1 ), matrix, position1 ); VectorTransform( *vertData->Position( vertex2 ), matrix, position2 ); VectorTransform( *vertData->Position( vertex3 ), matrix, position3 ); // printf( "\ngl 3\n" ); // printf( "gl %6.3f %6.3f %6.3f 1 0 0\n", XYZ(position1)); // printf( "gl %6.3f %6.3f %6.3f 0 1 0\n", XYZ(position2)); // printf( "gl %6.3f %6.3f %6.3f 0 0 1\n", XYZ(position3)); g_RtEnv.AddTriangle( nProp, position1, position2, position3, Vector(0,0,0)); } } else { // all tris expected to be discrete tri lists // must fixme if stripping ever occurs printf("unexpected strips found\n"); Assert( 0 ); return; } } } } } } } }