void CPhysicsSystem::PhysicsSimulate() { CMiniProfilerGuard mpg(&g_mp_PhysicsSimulate); VPROF_BUDGET( "CPhysicsSystem::PhysicsSimulate", VPROF_BUDGETGROUP_PHYSICS ); float frametime = gpGlobals->frametime; if ( physenv ) { g_Collisions.BufferTouchEvents( true ); #ifdef _DEBUG physenv->DebugCheckContacts(); #endif frametime *= cl_phys_timescale.GetFloat(); int maxTicks = cl_phys_maxticks.GetInt(); if ( maxTicks ) { float maxFrameTime = physenv->GetDeltaFrameTime( maxTicks ) - 1e-4f; frametime = clamp( frametime, 0, maxFrameTime ); } physenv->Simulate( frametime ); int activeCount = physenv->GetActiveObjectCount(); g_mp_active_object_count.Add(activeCount); IPhysicsObject **pActiveList = NULL; if ( activeCount ) { PHYS_PROFILE(aUpdateActiveObjects) pActiveList = (IPhysicsObject **)stackalloc( sizeof(IPhysicsObject *)*activeCount ); physenv->GetActiveObjects( pActiveList ); for ( int i = 0; i < activeCount; i++ ) { C_BaseEntity *pEntity = reinterpret_cast<C_BaseEntity *>(pActiveList[i]->GetGameData()); if ( pEntity ) { //const CCollisionProperty *collProp = pEntity->CollisionProp(); //debugoverlay->AddBoxOverlay( collProp->GetCollisionOrigin(), collProp->OBBMins(), collProp->OBBMaxs(), collProp->GetCollisionAngles(), 190, 190, 0, 0, 0.01 ); if ( pEntity->CollisionProp()->DoesVPhysicsInvalidateSurroundingBox() ) { pEntity->CollisionProp()->MarkSurroundingBoundsDirty(); } pEntity->VPhysicsUpdate( pActiveList[i] ); IPhysicsShadowController *pShadow = pActiveList[i]->GetShadowController(); if ( pShadow ) { // active shadow object, check for error Vector pos, targetPos; QAngle rot, targetAngles; pShadow->GetTargetPosition( &targetPos, &targetAngles ); pActiveList[i]->GetPosition( &pos, &rot ); Vector delta = targetPos - pos; float dist = VectorNormalize(delta); bool bBlocked = false; if ( dist > cl_phys_block_dist.GetFloat() ) { Vector vel; pActiveList[i]->GetImplicitVelocity( &vel, NULL ); float proj = DotProduct(vel, delta); if ( proj < dist * cl_phys_block_fraction.GetFloat() ) { bBlocked = true; //Msg("%s was blocked %.3f (%.3f proj)!\n", pEntity->GetClassname(), dist, proj ); } } Vector targetAxis; float deltaTargetAngle; RotationDeltaAxisAngle( rot, targetAngles, targetAxis, deltaTargetAngle ); if ( fabsf(deltaTargetAngle) > 0.5f ) { AngularImpulse angVel; pActiveList[i]->GetImplicitVelocity( NULL, &angVel ); float proj = DotProduct( angVel, targetAxis ) * Sign(deltaTargetAngle); if ( proj < (fabsf(deltaTargetAngle) * cl_phys_block_fraction.GetFloat()) ) { bBlocked = true; //Msg("%s was rot blocked %.3f proj %.3f!\n", pEntity->GetClassname(), deltaTargetAngle, proj ); } } if ( bBlocked ) { C_BaseEntity *pBlocker = FindPhysicsBlocker( pActiveList[i] ); if ( pBlocker ) { if ( IsBlockedShouldDisableCollisions( pEntity ) ) { PhysDisableEntityCollisions( pEntity, pBlocker ); pActiveList[i]->RecheckContactPoints(); // GetClassname returns a pointer to the same buffer always! //Msg("%s blocked !", pEntity->GetClassname() ); Msg("by %s\n", pBlocker->GetClassname() ); } } } } } } } #if 0 if ( cl_visualize_physics_shadows.GetBool() ) { int entityCount = NUM_ENT_ENTRIES; for ( int i = 0; i < entityCount; i++ ) { IClientEntity *pClientEnt = cl_entitylist->GetClientEntity(i); if ( !pClientEnt ) continue; C_BaseEntity *pEntity = pClientEnt->GetBaseEntity(); if ( !pEntity ) continue; Vector pos; QAngle angle; IPhysicsObject *pObj = pEntity->VPhysicsGetObject(); if ( !pObj || !pObj->GetShadowController() ) continue; pObj->GetShadowPosition( &pos, &angle ); debugoverlay->AddBoxOverlay( pos, pEntity->CollisionProp()->OBBMins(), pEntity->CollisionProp()->OBBMaxs(), angle, 255, 255, 0, 32, 0 ); char tmp[256]; V_snprintf( tmp, sizeof(tmp),"%s, (%s)\n", pEntity->GetClassname(), VecToString(angle) ); debugoverlay->AddTextOverlay( pos, 0, tmp ); } } #endif g_Collisions.BufferTouchEvents( false ); g_Collisions.FrameUpdate(); } physicssound::PlayImpactSounds( m_impactSounds ); }
void CPDumpPanel::Paint() { C_BaseEntity *ent = m_hDumpEntity; if ( !ent ) { Clear(); return; } // Now output the strings int x[5]; x[0] = 20; int columnwidth = 375; int numcols = ScreenWidth() / columnwidth; int i; numcols = clamp( numcols, 1, 5 ); for ( i = 0; i < numcols; i++ ) { if ( i == 0 ) { x[i] = 20; } else { x[i] = x[ i-1 ] + columnwidth - 20; } } int c = m_DumpEntityInfo.Size(); int fonttall = vgui::surface()->GetFontTall( m_FontSmall ) - 3; int fonttallMedium = vgui::surface()->GetFontTall( m_FontMedium ); int fonttallBig = vgui::surface()->GetFontTall( m_FontBig ); char currentclass[ 128 ]; currentclass[ 0 ] = 0; int starty = 60; int y = starty; int col = 0; int r = 255; int g = 255; int b = 255; int a = 255; char classextra[ 32 ]; classextra[ 0 ] = 0; char classprefix[ 32 ]; Q_strncpy( classprefix, "class ", sizeof( classprefix ) ); const char *classname = ent->GetClassname(); if ( !classname[ 0 ] ) { classname = typeid( *ent ).name(); Q_strncpy( classextra, " (classmap missing)", sizeof( classextra ) ); classprefix[ 0 ] = 0; } char sz[ 512 ]; wchar_t szconverted[ 1024 ]; surface()->DrawSetTextFont( m_FontBig ); surface()->DrawSetTextColor( Color( 255, 255, 255, 255 ) ); surface()->DrawSetTextPos( x[ col ] - 10, y - fonttallBig - 2 ); Q_snprintf( sz, sizeof( sz ), "entity # %i: %s%s%s", ent->entindex(), classprefix, classname, classextra ); g_pVGuiLocalize->ConvertANSIToUnicode( sz, szconverted, sizeof(szconverted) ); surface()->DrawPrintText( szconverted, wcslen( szconverted ) ); for ( i = 0; i < c; i++ ) { DumpInfo *slot = &m_DumpEntityInfo[ i ]; if ( stricmp( slot->classname, currentclass ) ) { y += 2; surface()->DrawSetTextFont( m_FontMedium ); surface()->DrawSetTextColor( Color( 0, 255, 100, 255 ) ); surface()->DrawSetTextPos( x[ col ] - 10, y ); Q_snprintf( sz, sizeof( sz ), "%s", slot->classname ); g_pVGuiLocalize->ConvertANSIToUnicode( sz, szconverted, sizeof(szconverted) ); surface()->DrawPrintText( szconverted, wcslen( szconverted ) ); y += fonttallMedium-1; Q_strncpy( currentclass, slot->classname, sizeof( currentclass ) ); } PredictionDumpColor( slot->networked, !slot->noterrorchecked, slot->differs, slot->withintolerance, r, g, b, a ); surface()->DrawSetTextFont( m_FontSmall ); surface()->DrawSetTextColor( Color( r, g, b, a ) ); surface()->DrawSetTextPos( x[ col ], y ); Q_snprintf( sz, sizeof( sz ), "%s", slot->fieldstring ); g_pVGuiLocalize->ConvertANSIToUnicode( sz, szconverted, sizeof(szconverted) ); surface()->DrawPrintText( szconverted, wcslen( szconverted ) ); y += fonttall; if ( y >= ScreenHeight() - fonttall - 60 ) { y = starty; col++; if ( col >= numcols ) break; } } surface()->DrawSetTextFont( m_FontSmall ); // Figure how far over the legend needs to be. const char *pFirstAndLongestString = "Not networked, no differences"; g_pVGuiLocalize->ConvertANSIToUnicode( pFirstAndLongestString, szconverted, sizeof(szconverted) ); int textSizeWide, textSizeTall; surface()->GetTextSize( m_FontSmall, szconverted, textSizeWide, textSizeTall ); // Draw a legend now int xpos = ScreenWidth() - textSizeWide - 5; y = ScreenHeight() - 7 * fonttall - 80; // Not networked, no differences PredictionDumpColor( false, false, false, false, r, g, b, a ); surface()->DrawSetTextColor( Color( r, g, b, a ) ); surface()->DrawSetTextPos( xpos, y ); Q_strncpy( sz, pFirstAndLongestString, sizeof( sz ) ); g_pVGuiLocalize->ConvertANSIToUnicode( sz, szconverted, sizeof(szconverted) ); surface()->DrawPrintText( szconverted, wcslen( szconverted ) ); y += fonttall; // Networked, no error check PredictionDumpColor( true, false, false, false, r, g, b, a ); surface()->DrawSetTextColor( Color( r, g, b, a ) ); surface()->DrawSetTextPos( xpos, y ); Q_strncpy( sz, "Networked, not checked", sizeof( sz ) ); g_pVGuiLocalize->ConvertANSIToUnicode( sz, szconverted, sizeof(szconverted) ); surface()->DrawPrintText( szconverted, wcslen( szconverted ) ); y += fonttall; // Networked, with error check PredictionDumpColor( true, true, false, false, r, g, b, a ); surface()->DrawSetTextColor( Color( r, g, b, a ) ); surface()->DrawSetTextPos( xpos, y ); Q_strncpy( sz, "Networked, error checked", sizeof( sz ) ); g_pVGuiLocalize->ConvertANSIToUnicode( sz, szconverted, sizeof(szconverted) ); surface()->DrawPrintText( szconverted, wcslen( szconverted ) ); y += fonttall; // Differs, but within tolerance PredictionDumpColor( true, true, true, true, r, g, b, a ); surface()->DrawSetTextColor( Color( r, g, b, a ) ); surface()->DrawSetTextPos( xpos, y ); Q_strncpy( sz, "Differs, but within tolerance", sizeof( sz ) ); g_pVGuiLocalize->ConvertANSIToUnicode( sz, szconverted, sizeof(szconverted) ); surface()->DrawPrintText( szconverted, wcslen( szconverted ) ); y += fonttall; // Differs, not within tolerance, but not networked PredictionDumpColor( false, true, true, false, r, g, b, a ); surface()->DrawSetTextColor( Color( r, g, b, a ) ); surface()->DrawSetTextPos( xpos, y ); Q_strncpy( sz, "Differs, but not networked", sizeof( sz ) ); g_pVGuiLocalize->ConvertANSIToUnicode( sz, szconverted, sizeof(szconverted) ); surface()->DrawPrintText( szconverted, wcslen( szconverted ) ); y += fonttall; // Differs, networked, not within tolerance PredictionDumpColor( true, true, true, false, r, g, b, a ); surface()->DrawSetTextColor( Color( r, g, b, a ) ); surface()->DrawSetTextPos( xpos, y ); Q_strncpy( sz, "Differs, networked", sizeof( sz ) ); g_pVGuiLocalize->ConvertANSIToUnicode( sz, szconverted, sizeof(szconverted) ); surface()->DrawPrintText( szconverted, wcslen( szconverted ) ); y += fonttall; }