collision scale for static prop scaling (uniformscale)

This commit is contained in:
PiMoNFeeD
2021-12-08 19:04:05 +03:00
parent af90a10c49
commit 6c11dd6732
6 changed files with 115 additions and 21 deletions

View File

@@ -392,6 +392,65 @@ vcollide_t* CM_VCollideForModel( int modelindex, const model_t* pModel )
return 0;
}
//-----------------------------------------------------------------------------
// returns a physcollide that is scaled based off input data
//-----------------------------------------------------------------------------
CPhysCollide* CM_ScalePhysCollide( vcollide_t *pVCollide, float flScale )
{
CPhysCollide *pNewCollide = pVCollide->solids[0];
if ( flScale != 1.0f )
{
// Create a query to get more information from the collision object
ICollisionQuery *pQuery = physcollision->CreateQueryModel( pVCollide->solids[0] ); // FIXME: This should iterate over all solids!
if ( pQuery == NULL )
return pVCollide->solids[0];
// Create a container to hold all the convexes we'll create
const int nNumConvex = pQuery->ConvexCount();
CPhysConvex **pConvexes = (CPhysConvex **) stackalloc( sizeof( CPhysConvex * ) * nNumConvex );
// For each convex, collect the verts and create a convex from it we'll retain for later
for ( int i = 0; i < nNumConvex; i++ )
{
int nNumTris = pQuery->TriangleCount( i );
int nNumVerts = nNumTris * 3;
// FIXME: Really? stackalloc?
Vector *pVerts = (Vector *) stackalloc( sizeof( Vector ) * nNumVerts );
Vector **ppVerts = (Vector **) stackalloc( sizeof( Vector * ) * nNumVerts );
for ( int j = 0; j < nNumTris; j++ )
{
// Get all the verts for this triangle and scale them up
pQuery->GetTriangleVerts( i, j, pVerts + (j * 3) );
*(pVerts + (j * 3)) *= flScale;
*(pVerts + (j * 3) + 1) *= flScale;
*(pVerts + (j * 3) + 2) *= flScale;
// Setup our pointers (blech!)
*(ppVerts + (j * 3)) = pVerts + (j * 3);
*(ppVerts + (j * 3) + 1) = pVerts + (j * 3) + 1;
*(ppVerts + (j * 3) + 2) = pVerts + (j * 3) + 2;
}
// Convert it back to a convex
pConvexes[i] = physcollision->ConvexFromVerts( ppVerts, nNumVerts );
Assert( pConvexes[i] != NULL );
if ( pConvexes[i] == NULL )
return pVCollide->solids[0];
}
// Clean up
physcollision->DestroyQueryModel( pQuery );
// Create a collision model from all the convexes
pNewCollide = physcollision->ConvertConvexToCollide( pConvexes, nNumConvex );
if ( !pNewCollide )
return pVCollide->solids[0];
}
return pNewCollide;
}

View File

@@ -80,6 +80,7 @@ int CM_BoxVisible( const Vector& mins, const Vector& maxs, const byte *visbits
typedef struct cmodel_collision_s cmodel_collision_t;
vcollide_t *CM_GetVCollide( int modelIndex );
vcollide_t* CM_VCollideForModel( int modelindex, const model_t* pModel );
CPhysCollide* CM_ScalePhysCollide( vcollide_t *pVCollide, float flScale );
// gets a virtual physcollide for a displacement
CPhysCollide *CM_PhysCollideForDisp( int index );

View File

@@ -861,11 +861,15 @@ bool CEngineTrace::ClipRayToVPhysics( const Ray_t &ray, unsigned int fMask, ICol
vcollide_t *pCollide = g_pMDLCache->GetVCollide( pModel->studio );
if ( pCollide && pCollide->solidCount )
{
CPhysCollide *pPhysCollide = pCollide->solids[0]; // UNDONE: Support other solid indices?!?!?!? (forced zero)
if ( StaticPropMgr()->IsStaticProp( pEntity->GetEntityHandle() ) )
pPhysCollide = StaticPropMgr()->GetStaticPropCollide( pEntity->GetEntityHandle() );
physcollision->TraceBox(
ray,
fMask,
&studioConvex,
pCollide->solids[0], // UNDONE: Support other solid indices?!?!?!? (forced zero)
pPhysCollide,
pEntity->GetCollisionOrigin(),
pEntity->GetCollisionAngles(),
pTrace );

View File

@@ -315,7 +315,10 @@ private:
Vector m_RenderBBoxMin;
Vector m_RenderBBoxMax;
matrix3x4_t m_ModelToWorld;
matrix3x4_t m_ModelToWorldPreScaled;
float m_flRadius;
Vector m_ModelBBoxMin;
Vector m_ModelBBoxMax;
Vector m_WorldRenderBBoxMin;
Vector m_WorldRenderBBoxMax;
@@ -327,6 +330,7 @@ private:
// CSGO port
Vector4D m_DiffuseModulation;
float m_Scale;
CPhysCollide *m_pPhysCollide;
};
@@ -355,6 +359,7 @@ public:
virtual bool IsStaticProp( CBaseHandle handle ) const;
virtual int GetStaticPropIndex( IHandleEntity *pHandleEntity ) const;
virtual ICollideable *GetStaticPropByIndex( int propIndex );
virtual CPhysCollide *GetStaticPropCollide( IHandleEntity *pHandleEntity ) const;
// methods of IStaticPropMgrClient
virtual void ComputePropOpacity( const Vector &viewOrigin, float factor );
@@ -497,6 +502,7 @@ bool CStaticProp::Init( int index, StaticPropLump_t &lump, model_t *pModel )
m_LeafCount = lump.m_LeafCount;
m_nSolidType = lump.m_Solid;
m_FadeIndex = INVALID_FADE_INDEX;
m_pPhysCollide = NULL;
MDLCACHE_CRITICAL_SECTION_( g_pMDLCache );
@@ -551,17 +557,18 @@ bool CStaticProp::Init( int index, StaticPropLump_t &lump, model_t *pModel )
}
// Cache the model to world matrix since it never changes.
AngleMatrix( lump.m_Angles, lump.m_Origin, m_ModelToWorld );
matrix3x4_t matScale;
SetScaleMatrix(Vector(m_Scale), matScale);
MatrixMultiply(m_ModelToWorld, matScale, m_ModelToWorld);
AngleMatrix( lump.m_Angles, lump.m_Origin, m_ModelToWorldPreScaled );
MatrixCopy( m_ModelToWorldPreScaled, m_ModelToWorld );
MatrixScaleBy( m_Scale, m_ModelToWorld );
// Cache the collision bounding box since it'll never change.
modelinfo->GetModelRenderBounds( m_pModel, m_RenderBBoxMin, m_RenderBBoxMax );
m_flRadius = m_RenderBBoxMin.DistTo( m_RenderBBoxMax ) * 0.5f;
TransformAABB( m_ModelToWorld, m_RenderBBoxMin, m_RenderBBoxMax, m_WorldRenderBBoxMin, m_WorldRenderBBoxMax );
m_ModelBBoxMin = m_pModel->mins * m_Scale;
m_ModelBBoxMax = m_pModel->maxs * m_Scale;
// FIXME: Sucky, but unless we want to re-read the static prop lump when the client is
// initialized (possible, but also gross), we need to cache off the illum center now
if (lump.m_Flags & STATIC_PROP_USE_LIGHTING_ORIGIN)
@@ -608,7 +615,7 @@ const Vector& CStaticProp::OBBMins( ) const
{
if ( GetSolid() == SOLID_VPHYSICS )
{
return m_pModel->mins;
return m_ModelBBoxMin;
}
Vector& tv = AllocTempVector();
// FIXME: why doesn't this just return m_RenderBBoxMin?
@@ -620,7 +627,7 @@ const Vector& CStaticProp::OBBMaxs( ) const
{
if ( GetSolid() == SOLID_VPHYSICS )
{
return m_pModel->maxs;
return m_ModelBBoxMax;
}
Vector& tv = AllocTempVector();
// FIXME: why doesn't this just return m_RenderBBoxMax?
@@ -844,7 +851,9 @@ const QAngle& CStaticProp::GetCollisionAngles() const
const matrix3x4_t& CStaticProp::CollisionToWorldTransform() const
{
return m_ModelToWorld;
// PiMoN: in theory, this shouldn't be scaled as the physics mesh is being scaled separately
// but I dont remember whether changing this had any effect at all.
return m_ModelToWorldPreScaled;
}
@@ -1067,7 +1076,7 @@ int CStaticProp::DrawModelSlow( int flags )
else if ( m_nSolidType == SOLID_BBOX )
{
static Color debugColor( 0, 255, 255, 255 );
RenderWireframeBox( m_Origin, vec3_angle, m_pModel->mins, m_pModel->maxs, debugColor, true );
RenderWireframeBox( m_Origin, m_Angles, m_ModelBBoxMin, m_ModelBBoxMax, debugColor, true );
}
}
@@ -1185,7 +1194,7 @@ void CStaticProp::InsertPropIntoKDTree()
Vector mins, maxs;
matrix3x4_t propToWorld;
AngleMatrix( m_Angles, m_Origin, propToWorld );
TransformAABB( propToWorld, m_pModel->mins, m_pModel->maxs, mins, maxs );
TransformAABB( propToWorld, m_ModelBBoxMin, m_ModelBBoxMax, mins, maxs );
// If it's using vphysics, get a good AABB
if ( m_nSolidType == SOLID_VPHYSICS )
@@ -1193,7 +1202,7 @@ void CStaticProp::InsertPropIntoKDTree()
vcollide_t *pCollide = CM_VCollideForModel( -1, m_pModel );
if ( pCollide && pCollide->solidCount )
{
physcollision->CollideGetAABB( &mins, &maxs, pCollide->solids[0], m_Origin, m_Angles );
physcollision->CollideGetAABB( &mins, &maxs, CM_ScalePhysCollide( pCollide, m_Scale ), m_Origin, m_Angles );
}
else
{
@@ -1246,7 +1255,7 @@ void CStaticProp::CreateVPhysics( IPhysicsEnvironment *pPhysEnv, IVPhysicsKeyHan
if (pVCollide)
{
pPhysCollide = pVCollide->solids[0];
pPhysCollide = CM_ScalePhysCollide( pVCollide, m_Scale );
IVPhysicsKeyParser *pParse = physcollision->VPhysicsKeyParserCreate( pVCollide->pKeyValues );
while ( !pParse->Finished() )
@@ -1280,7 +1289,7 @@ void CStaticProp::CreateVPhysics( IPhysicsEnvironment *pPhysEnv, IVPhysicsKeyHan
#endif
// If there's no collide, we need a bbox...
pPhysCollide = physcollision->BBoxToCollide( m_pModel->mins, m_pModel->maxs );
pPhysCollide = physcollision->BBoxToCollide( m_ModelBBoxMin, m_ModelBBoxMax );
solid.params = g_PhysDefaultObjectParams;
}
@@ -1293,6 +1302,7 @@ void CStaticProp::CreateVPhysics( IPhysicsEnvironment *pPhysEnv, IVPhysicsKeyHan
pPhysEnv->CreatePolyObjectStatic( pPhysCollide,
surfaceData, m_Origin, m_Angles, &solid.params );
//PhysCheckAdd( pPhys, "Static" );
m_pPhysCollide = pPhysCollide;
}
@@ -1901,6 +1911,17 @@ bool CStaticPropMgr::PropHasBakedLightingDisabled( IHandleEntity *pHandleEntity
return ( (prop.Flags() & STATIC_PROP_NO_PER_VERTEX_LIGHTING ) != 0 );
}
CPhysCollide *CStaticPropMgr::GetStaticPropCollide( IHandleEntity *pHandleEntity ) const
{
// Strip off the bits
int nIndex = HandleEntityToIndex( pHandleEntity );
// Get the prop
const CStaticProp &prop = m_StaticProps[nIndex];
return prop.m_pPhysCollide;
}
//-----------------------------------------------------------------------------
// Compute static lighting
//-----------------------------------------------------------------------------

View File

@@ -69,6 +69,8 @@ public:
virtual int GetStaticPropIndex( IHandleEntity *pHandleEntity ) const = 0;
virtual bool PropHasBakedLightingDisabled( IHandleEntity *pHandleEntity) const = 0;
virtual CPhysCollide *GetStaticPropCollide( IHandleEntity *pHandleEntity ) const = 0;
};

View File

@@ -232,7 +232,7 @@ static void ConvertTexelDataToTexture(unsigned int _resX, unsigned int _resY, Im
// Such a monstrosity. :(
static void GenerateLightmapSamplesForMesh( const matrix3x4_t& _matPos, const matrix3x4_t& _matNormal, int _iThread, int _skipProp, int _nFlags, int _lightmapResX, int _lightmapResY,
studiohdr_t* _pStudioHdr, mstudiomodel_t* _pStudioModel, OptimizedModel::ModelHeader_t* _pVtxModel, int _meshID,
studiohdr_t* _pStudioHdr, mstudiomodel_t* _pStudioModel, OptimizedModel::ModelHeader_t* _pVtxModel, int _meshID, float _flScale,
CComputeStaticPropLightingResults *_pResults );
// Debug function, converts lightmaps to linear space then dumps them out.
@@ -320,6 +320,8 @@ private:
unsigned int m_LightmapImageWidth;
unsigned int m_LightmapImageHeight;
float m_Scale;
};
// Enumeration context
@@ -1047,6 +1049,8 @@ void CVradStaticPropMgr::UnserializeModels( CUtlBuffer& buf )
m_StaticProps[i].m_LightmapImageFormat = IMAGE_FORMAT_RGB888;
m_StaticProps[i].m_LightmapImageWidth = lump.m_nLightmapResolutionX;
m_StaticProps[i].m_LightmapImageHeight = lump.m_nLightmapResolutionY;
m_StaticProps[i].m_Scale = lump.m_Scale;
}
}
@@ -1370,7 +1374,7 @@ void CVradStaticPropMgr::ComputeLighting( CStaticProp &prop, int iThread, int pr
// TODO: Move this into its own function. In fact, refactor this whole function.
if (withTexelLighting)
{
GenerateLightmapSamplesForMesh( matPos, matNormal, iThread, skip_prop, nFlags, prop.m_LightmapImageWidth, prop.m_LightmapImageHeight, pStudioHdr, pStudioModel, pVtxModel, meshID, pResults );
GenerateLightmapSamplesForMesh( matPos, matNormal, iThread, skip_prop, nFlags, prop.m_LightmapImageWidth, prop.m_LightmapImageHeight, pStudioHdr, pStudioModel, pVtxModel, meshID, prop.m_Scale, pResults );
}
// If we do lightmapping, we also do vertex lighting as a potential fallback. This may change.
@@ -1379,7 +1383,7 @@ void CVradStaticPropMgr::ComputeLighting( CStaticProp &prop, int iThread, int pr
Vector sampleNormal;
Vector samplePosition;
// transform position and normal into world coordinate system
VectorTransform(*vertData->Position(vertexID), matPos, samplePosition);
VectorTransform(*vertData->Position(vertexID) * prop.m_Scale, matPos, samplePosition);
VectorTransform(*vertData->Normal(vertexID), matNormal, sampleNormal);
if ( PositionInSolid( samplePosition ) )
@@ -1843,6 +1847,7 @@ void CVradStaticPropMgr::AddPolysForRayTrace( void )
{
Vector verts[3];
queryModel->GetTriangleVerts( nConvex, nTri, verts );
*verts *= prop.m_Scale; // TODO: is it needed?
for ( int nVert = 0; nVert < 3; ++nVert )
verts[nVert] = xform.VMul4x3(verts[nVert]);
g_RtEnv.AddTriangle ( TRACE_ID_STATICPROP | nProp, verts[0], verts[1], verts[2], fullCoverage );
@@ -1945,6 +1950,7 @@ void CVradStaticPropMgr::AddPolysForRayTrace( void )
// transform position into world coordinate system
matrix3x4_t matrix;
AngleMatrix( prop.m_Angles, prop.m_Origin, matrix );
MatrixScaleBy( prop.m_Scale, matrix );
Vector position1;
Vector position2;
@@ -2129,6 +2135,7 @@ void CVradStaticPropMgr::BuildTriList( CStaticProp &prop )
// transform position into world coordinate system
matrix3x4_t matrix;
AngleMatrix( prop.m_Angles, prop.m_Origin, matrix );
MatrixScaleBy( prop.m_Scale, matrix );
Vector position1;
Vector position2;
@@ -2274,7 +2281,7 @@ inline float ComputeBarycentricDistanceToTri( Vector _barycentricCoord, Vector2D
}
// ------------------------------------------------------------------------------------------------
static void GenerateLightmapSamplesForMesh( const matrix3x4_t& _matPos, const matrix3x4_t& _matNormal, int _iThread, int _skipProp, int _flags, int _lightmapResX, int _lightmapResY, studiohdr_t* _pStudioHdr, mstudiomodel_t* _pStudioModel, OptimizedModel::ModelHeader_t* _pVtxModel, int _meshID, CComputeStaticPropLightingResults *_outResults )
static void GenerateLightmapSamplesForMesh( const matrix3x4_t& _matPos, const matrix3x4_t& _matNormal, int _iThread, int _skipProp, int _flags, int _lightmapResX, int _lightmapResY, studiohdr_t* _pStudioHdr, mstudiomodel_t* _pStudioModel, OptimizedModel::ModelHeader_t* _pVtxModel, int _meshID, float _flScale, CComputeStaticPropLightingResults *_outResults )
{
// Could iterate and gen this if needed.
int nLod = 0;
@@ -2323,9 +2330,9 @@ static void GenerateLightmapSamplesForMesh( const matrix3x4_t& _matPos, const ma
int vertex3 = pStripGroup->pVertex(i3)->origMeshVertID;
Vector modelPos[3] = {
*vertData->Position(vertex1),
*vertData->Position(vertex2),
*vertData->Position(vertex3)
*vertData->Position(vertex1)* _flScale,
*vertData->Position(vertex2)* _flScale,
*vertData->Position(vertex3)* _flScale
};
Vector modelNormal[3] = {