void CPlayerPickupController::Init( CBasePlayer *pPlayer, CBaseEntity *pObject ) { m_pPlayer = pPlayer; IPhysicsObject *pPhysics = pObject->VPhysicsGetObject(); Vector position; QAngle angles; pPhysics->GetPosition( &position, &angles ); m_grabController.SetMaxImpulse( Vector(20*100,20*100,20*100), AngularImpulse(20*180,20*180,20*180) ); m_grabController.AttachEntity( pObject, pPhysics, position, angles ); // Holster player's weapon if ( m_pPlayer->GetActiveWeapon() ) { if ( !m_pPlayer->GetActiveWeapon()->Holster() ) { Shutdown(); return; } } m_pPlayer->m_Local.m_iHideHUD |= HIDEHUD_WEAPONS; m_pPlayer->SetUseEntity( this ); matrix3x4_t tmp; ComputePlayerMatrix( tmp ); VectorITransform( position, tmp, m_positionPlayerSpace ); // UNDONE: This algorithm needs a bit more thought. REVISIT. // put the bottom of the object arms' length below eye level // get bottommost point of object Vector bottom = physcollision->CollideGetExtent( pPhysics->GetCollide(), vec3_origin, angles, Vector(0,0,-1) ); // get the real eye origin Vector playerEye = pPlayer->EyePosition(); // move target up so that bottom of object is at PLAYER_HOLD_LEVEL z in local space // float delta = PLAYER_HOLD_LEVEL_EYES - bottom.z - m_positionPlayerSpace.z; float delta = 0; // player can reach down 2ft below his feet float maxPickup = (playerEye.z + PLAYER_HOLD_LEVEL_EYES) - (pPlayer->GetAbsMins().z - PLAYER_REACH_DOWN_DISTANCE); delta = clamp( delta, pPlayer->WorldAlignMins().z, maxPickup ); m_positionPlayerSpace.z += delta; m_anglesPlayerSpace = TransformAnglesToLocalSpace( angles, tmp ); m_anglesPlayerSpace = AlignAngles( m_anglesPlayerSpace, DOT_30DEGREE ); // re-transform and check angles = TransformAnglesToWorldSpace( m_anglesPlayerSpace, tmp ); VectorTransform( m_positionPlayerSpace, tmp, position ); // hackhack: Move up to eye position for the check float saveZ = position.z; position.z = playerEye.z; CheckObjectPosition( position, angles, position ); // move back to original position position.z = saveZ; VectorITransform( position, tmp, m_positionPlayerSpace ); }
void RagdollComputeExactBbox( const ragdoll_t &ragdoll, const Vector &origin, Vector &outMins, Vector &outMaxs ) { outMins = origin; outMaxs = origin; for ( int i = 0; i < ragdoll.listCount; i++ ) { Vector mins, maxs; Vector objectOrg; QAngle objectAng; IPhysicsObject *pObject = ragdoll.list[i].pObject; pObject->GetPosition( &objectOrg, &objectAng ); physcollision->CollideGetAABB( mins, maxs, pObject->GetCollide(), objectOrg, objectAng ); for ( int j = 0; j < 3; j++ ) { if ( mins[j] < outMins[j] ) { outMins[j] = mins[j]; } if ( maxs[j] > outMaxs[j] ) { outMaxs[j] = maxs[j]; } } } }
//----------------------------------------------------------------------------- // Purpose: Returns the magnitude of the entity's angular velocity. //----------------------------------------------------------------------------- float CPointAngularVelocitySensor::SampleAngularVelocity(CBaseEntity *pEntity) { if (pEntity->GetMoveType() == MOVETYPE_VPHYSICS) { IPhysicsObject *pPhys = pEntity->VPhysicsGetObject(); if (pPhys != NULL) { Vector vecVelocity; AngularImpulse vecAngVelocity; pPhys->GetVelocity(&vecVelocity, &vecAngVelocity); QAngle angles; pPhys->GetPosition( NULL, &angles ); float dt = gpGlobals->curtime - GetLastThink(); if ( dt == 0 ) dt = 0.1; // HACKHACK: We don't expect a real 'delta' orientation here, just enough of an error estimate to tell if this thing // is trying to move, but failing. QAngle delta = angles - m_lastOrientation; if ( ( delta.Length() / dt ) < ( vecAngVelocity.Length() * 0.01 ) ) { return 0.0f; } m_lastOrientation = angles; if ( m_bUseHelper == false ) { return vecAngVelocity.Length(); } else { Vector vLine = m_vecAxis - GetAbsOrigin(); VectorNormalize( vLine ); Vector vecWorldAngVelocity; pPhys->LocalToWorldVector( &vecWorldAngVelocity, vecAngVelocity ); float flDot = DotProduct( vecWorldAngVelocity, vLine ); return flDot; } } } else { QAngle vecAngVel = pEntity->GetLocalAngularVelocity(); float flMax = MAX(fabs(vecAngVel[PITCH]), fabs(vecAngVel[YAW])); return MAX(flMax, fabs(vecAngVel[ROLL])); } return 0; }
//Actual work code IterationRetval_t EnumElement( IHandleEntity *pHandleEntity ) { C_BaseEntity *pEnt = ClientEntityList().GetBaseEntityFromHandle( pHandleEntity->GetRefEHandle() ); if ( pEnt == NULL ) return ITERATION_CONTINUE; C_BaseAnimating *pModel = static_cast< C_BaseAnimating * >( pEnt ); if ( pModel == NULL ) return ITERATION_CONTINUE; trace_t tr; enginetrace->ClipRayToEntity( m_rayShot, MASK_SHOT, pModel, &tr ); IPhysicsObject *pPhysicsObject = pModel->VPhysicsGetObject(); if ( pPhysicsObject == NULL ) return ITERATION_CONTINUE; if ( tr.fraction < 1.0 ) { IPhysicsObject *pReference = GetWorldPhysObject(); if ( !pReference || !pPhysicsObject ) return ITERATION_CONTINUE; constraint_ballsocketparams_t ballsocket; ballsocket.Defaults(); Vector Origin; pPhysicsObject->GetPosition( &Origin, NULL ); if ( ( Origin- m_vWorld).Length () < 64 ) { pReference->WorldToLocal( ballsocket.constraintPosition[0], m_vWorld ); pPhysicsObject->WorldToLocal( ballsocket.constraintPosition[1], Origin ); GetBreakParams( ballsocket.constraint ); ballsocket.constraint.torqueLimit = 0; m_pConstraint = physenv->CreateBallsocketConstraint( pReference, pPhysicsObject, NULL, ballsocket ); pPhysicsObject->ApplyForceCenter( Vector(0, 0, 1 ) * 100); return ITERATION_STOP; } else return ITERATION_CONTINUE; } return ITERATION_CONTINUE; }
bool CStatueProp::TestCollision( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr ) { IPhysicsObject *pPhysObject = VPhysicsGetObject(); if ( pPhysObject ) { Vector vecPosition; QAngle vecAngles; pPhysObject->GetPosition( &vecPosition, &vecAngles ); const CPhysCollide *pScaledCollide = pPhysObject->GetCollide(); physcollision->TraceBox( ray, pScaledCollide, vecPosition, vecAngles, &tr ); return tr.DidHit(); } return false; }
//----------------------------------------------------------------------------- // Purpose: // Input : *pController - // *pObject - // deltaTime - // &linear - // &angular - // Output : IMotionEvent::simresult_e //----------------------------------------------------------------------------- IMotionEvent::simresult_e CAI_BasePhysicsFlyingBot::Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular ) { static int count; IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); // Assert( pPhysicsObject ); if (!pPhysicsObject) return SIM_NOTHING; // move Vector actualVelocity; AngularImpulse actualAngularVelocity; pPhysicsObject->GetVelocity( &actualVelocity, &actualAngularVelocity ); linear = (m_vCurrentVelocity - actualVelocity) * (0.1 / deltaTime) * 10.0; /* DevMsg("Sim %d : %5.1f %5.1f %5.1f\n", count++, m_vCurrentVelocity.x - actualVelocity.x, m_vCurrentVelocity.y - actualVelocity.y, m_vCurrentVelocity.z - actualVelocity.z ); */ // do angles. Vector actualPosition; QAngle actualAngles; pPhysicsObject->GetPosition( &actualPosition, &actualAngles ); // FIXME: banking currently disabled, forces simple upright posture angular.x = (UTIL_AngleDiff( m_vCurrentBanking.z, actualAngles.z ) - actualAngularVelocity.x) * (1 / deltaTime); angular.y = (UTIL_AngleDiff( m_vCurrentBanking.x, actualAngles.x ) - actualAngularVelocity.y) * (1 / deltaTime); // turn toward target angular.z = UTIL_AngleDiff( m_fHeadYaw, actualAngles.y + actualAngularVelocity.z * 0.1 ) * (1 / deltaTime); // angular = m_vCurrentAngularVelocity - actualAngularVelocity; // DevMsg("Sim %d : %.1f %.1f %.1f (%.1f)\n", count++, actualAngles.x, actualAngles.y, actualAngles.z, m_fHeadYaw ); // FIXME: remove the stuff from MoveExecute(); // FIXME: check MOVE? ClampMotorForces( linear, angular ); return SIM_GLOBAL_ACCELERATION; // on my local axis. SIM_GLOBAL_ACCELERATION }
void C_PhysPropClientside::Break() { m_takedamage = DAMAGE_NO; IPhysicsObject *pPhysics = VPhysicsGetObject(); Vector velocity; AngularImpulse angVelocity; Vector origin; QAngle angles; AddSolidFlags( FSOLID_NOT_SOLID ); if ( pPhysics ) { pPhysics->GetVelocity( &velocity, &angVelocity ); pPhysics->GetPosition( &origin, &angles ); pPhysics->RecheckCollisionFilter(); } else { velocity = GetAbsVelocity(); QAngleToAngularImpulse( GetLocalAngularVelocity(), angVelocity ); origin = GetAbsOrigin(); angles = GetAbsAngles(); } breakablepropparams_t params( origin, angles, velocity, angVelocity ); params.impactEnergyScale = m_impactEnergyScale; params.defCollisionGroup = GetCollisionGroup(); if ( params.defCollisionGroup == COLLISION_GROUP_NONE ) { // don't automatically make anything COLLISION_GROUP_NONE or it will // collide with debris being ejected by breaking params.defCollisionGroup = COLLISION_GROUP_INTERACTIVE; } // no damage/damage force? set a burst of 100 for some movement params.defBurstScale = 100; // spwan break chunks PropBreakableCreateAll( GetModelIndex(), pPhysics, params, this, -1, false ); Release(); // destroy object }
//----------------------------------------------------------------------------- // Purpose: Used to tell whether an item may be picked up by the player. This // accounts for solid obstructions being in the way. // Input : *pItem - item in question // *pPlayer - player attempting the pickup // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- bool UTIL_ItemCanBeTouchedByPlayer( CBaseEntity *pItem, CBasePlayer *pPlayer ) { if ( pItem == NULL || pPlayer == NULL ) return false; // For now, always allow a vehicle riding player to pick up things they're driving over if ( pPlayer->IsInAVehicle() ) return true; // Get our test positions Vector vecStartPos; IPhysicsObject *pPhysObj = pItem->VPhysicsGetObject(); if ( pPhysObj != NULL ) { // Use the physics hull's center QAngle vecAngles; pPhysObj->GetPosition( &vecStartPos, &vecAngles ); } else { // Use the generic bbox center vecStartPos = pItem->CollisionProp()->WorldSpaceCenter(); } Vector vecEndPos = pPlayer->EyePosition(); // FIXME: This is the simple first try solution towards the problem. We need to take edges and shape more into account // for this to be fully robust. // Trace between to see if we're occluded trace_t tr; CTraceFilterSkipTwoEntities filter( pPlayer, pItem, COLLISION_GROUP_PLAYER_MOVEMENT ); UTIL_TraceLine( vecStartPos, vecEndPos, MASK_SOLID, &filter, &tr ); // Occluded // FIXME: For now, we exclude starting in solid because there are cases where this doesn't matter if ( tr.fraction < 1.0f ) return false; return true; }
void PhysicsSceneRenderer::Render(PhysicsScene *p_scene, Camera *p_camera) { vec4 planes[6]; p_camera->getFrustumPlanes(planes); auto & cloths = p_scene->GetCloths(); for (auto iter = cloths.begin(); iter != cloths.end(); ++iter) { ICloth *cloth = (*iter); IPhysicsObject ** nodes = cloth->GetNodes(); for (unsigned int r = 0; r < cloth->GetHeight() - 1; ++r) { for (unsigned int c = 0; c < cloth->GetWidth() - 1; ++c) { { auto obj0 = nodes[r * cloth->GetWidth() + c]; auto obj1 = nodes[(r + 1) * cloth->GetWidth() + c]; auto obj2 = nodes[(r + 1) * cloth->GetWidth() + (c + 1)]; auto col0 = GetRenderInfo(obj0).m_colour; auto col1 = GetRenderInfo(obj1).m_colour; auto col2 = GetRenderInfo(obj2).m_colour; auto col = glm::mix(col0, glm::mix(col1, col2, 0.5F), 0.6667F); col.a = 1.0F; if (!(obj0->GetHasConstraintBroke() || obj1->GetHasConstraintBroke() || obj2->GetHasConstraintBroke())) Gizmos::addTri(obj0->GetPosition(), obj1->GetPosition(), obj2->GetPosition(), col); } { auto obj0 = nodes[r * cloth->GetWidth() + c]; auto obj1 = nodes[(r + 1) * cloth->GetWidth() + (c + 1)]; auto obj2 = nodes[r * cloth->GetWidth() + (c + 1)]; auto col0 = GetRenderInfo(obj0).m_colour; auto col1 = GetRenderInfo(obj1).m_colour; auto col2 = GetRenderInfo(obj2).m_colour; auto col = glm::mix(col0, glm::mix(col1, col2, 0.5F), 0.6667F); col.a = 1.0F; if (!(obj0->GetHasConstraintBroke() || obj1->GetHasConstraintBroke() || obj2->GetHasConstraintBroke())) Gizmos::addTri(obj0->GetPosition(), obj1->GetPosition(), obj2->GetPosition(), col); } } } } int activeObjects = 0; auto & objects = p_scene->GetPhysicsObjects(); for (auto iter = objects.begin(); iter != objects.end(); ++iter) { IPhysicsObject *obj = (*iter); activeObjects += obj->GetIsAwake(); RenderInfo &info = GetRenderInfo(obj); auto col = info.m_colour; if (col.a == 0.0F) continue; ICollider * collider = obj->GetCollider(); switch (collider->GetType()) { case ICollider::Type::SPHERE: { float r = ((SphereCollider*)collider)->GetRadius(); bool hidden = false; for (int i = 0; i < 6; i++) { float d = glm::dot(vec3(planes[i]), obj->GetPosition()) + planes[i].w; if (d < -r) { hidden = true; continue; } } if (hidden) continue; if (obj->GetIsAwake()) { int j = glm::clamp((int)(r * 4), 2, 4); Gizmos::addSphere(obj->GetPosition(), r, j, j * 2, col); } else { float r = ((SphereCollider*)collider)->GetRadius(); Gizmos::addAABBFilled(obj->GetPosition(), vec3(r * 0.875F), col); } } break; case ICollider::Type::PLANE: { vec3 planeNormal = ((PlaneCollider*)collider)->GetNormal(); float planeDistance = ((PlaneCollider*)collider)->GetDistance(); glm::mat4 normMatrix = glm::lookAt(vec3(0), planeNormal, vec3(0.000001F, 1, 0)); vec3 corners[4] = { vec3(vec4(-9999, -9999, -planeDistance, 1) * normMatrix), vec3(vec4(-9999, +9999, -planeDistance, 1) * normMatrix), vec3(vec4(+9999, +9999, -planeDistance, 1) * normMatrix), vec3(vec4(+9999, -9999, -planeDistance, 1) * normMatrix), }; Gizmos::addTri(corners[0], corners[1], corners[2], col); Gizmos::addTri(corners[0], corners[2], corners[3], col); } break; case ICollider::Type::AABB: { const vec3 & position = ((AABBCollider*)collider)->GetPosition(); const vec3 & extends = ((AABBCollider*)collider)->GetHalfExtents(); Gizmos::addAABBFilled(position, extends, col); } break; } } auto & constraints = p_scene->GetConstraints(); for (auto iter = constraints.begin(); iter != constraints.end(); ++iter) { IConstraint *con = (*iter); auto col0 = GetRenderInfo(con->GetObject1()).m_colour; /* if (col0.a == 0.0F) continue;*/ auto col1 = GetRenderInfo(con->GetObject1()).m_colour; /* if (col1.a == 0.0F) continue;*/ auto col = glm::mix(col0, col1, 0.5F); col.a = 1.0F; Gizmos::addLine(con->GetObject1()->GetPosition(), con->GetObject2()->GetPosition(), col); } //printf("Physics Objects: %d [AWAKE] / %d [TOTAL]\n", activeObjects, objects.size()); }
void CWeaponGravityGun::EffectUpdate( void ) { Vector start, forward, right; trace_t tr; CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); if ( !pOwner ) return; pOwner->EyeVectors( &forward, &right, NULL ); start = pOwner->Weapon_ShootPosition(); TraceLine( &tr ); Vector end = tr.endpos; float distance = tr.fraction * 4096; if ( m_hObject == NULL && tr.DidHitNonWorldEntity() ) { CBaseEntity *pEntity = tr.m_pEnt; AttachObject( pEntity, GetPhysObjFromPhysicsBone( pEntity, tr.physicsbone ), tr.physicsbone, start, tr.endpos, distance ); } // Add the incremental player yaw to the target transform QAngle angles = m_gravCallback.TransformAnglesFromPlayerSpace( m_gravCallback.m_targetRotation, pOwner ); CBaseEntity *pObject = m_hObject; if ( pObject ) { if ( m_useDown ) { if ( pOwner->m_afButtonPressed & IN_USE ) { m_useDown = false; } } else { if ( pOwner->m_afButtonPressed & IN_USE ) { m_useDown = true; } } if ( m_useDown ) { #ifndef CLIENT_DLL pOwner->SetPhysicsFlag( PFLAG_DIROVERRIDE, true ); #endif if ( pOwner->m_nButtons & IN_FORWARD ) { m_distance = Approach( 1024, m_distance, gpGlobals->frametime * 100 ); } if ( pOwner->m_nButtons & IN_BACK ) { m_distance = Approach( 40, m_distance, gpGlobals->frametime * 100 ); } } if ( pOwner->m_nButtons & IN_WEAPON1 ) { m_distance = Approach( 1024, m_distance, m_distance * 0.1 ); } if ( pOwner->m_nButtons & IN_WEAPON2 ) { m_distance = Approach( 40, m_distance, m_distance * 0.1 ); } IPhysicsObject *pPhys = GetPhysObjFromPhysicsBone( pObject, m_physicsBone ); if ( pPhys ) { if ( pPhys->IsAsleep() ) { // on the odd chance that it's gone to sleep while under anti-gravity pPhys->Wake(); } Vector newPosition = start + forward * m_distance; Vector offset; pPhys->LocalToWorld( &offset, m_worldPosition ); Vector vecOrigin; pPhys->GetPosition( &vecOrigin, NULL ); m_gravCallback.SetTargetPosition( newPosition + (vecOrigin - offset), angles ); Vector dir = (newPosition - pObject->GetLocalOrigin()); m_movementLength = dir.Length(); } } else { m_targetPosition = end; //m_gravCallback.SetTargetPosition( end, m_gravCallback.m_targetRotation ); } }
void CHLPlayerMove::FinishMove( CBasePlayer *player, CUserCmd *ucmd, CMoveData *move ) { // Call the default FinishMove code. BaseClass::FinishMove( player, ucmd, move ); if ( gpGlobals->frametime != 0 ) { float distance = 0.0f; IServerVehicle *pVehicle = player->GetVehicle(); if ( pVehicle ) { pVehicle->FinishMove( player, ucmd, move ); IPhysicsObject *obj = player->GetVehicleEntity()->VPhysicsGetObject(); if ( obj ) { Vector newPos; obj->GetPosition( &newPos, NULL ); distance = VectorLength( newPos - m_vecSaveOrigin ); if ( m_vecSaveOrigin == vec3_origin || distance > 100.0f ) distance = 0.0f; m_vecSaveOrigin = newPos; } CPropVehicleDriveable *driveable = dynamic_cast< CPropVehicleDriveable * >( player->GetVehicleEntity() ); if ( driveable ) { // Overturned and at rest (if still moving it can fix itself) bool bFlipped = driveable->IsOverturned() && ( distance < 0.5f ); if ( m_bVehicleFlipped != bFlipped ) { if ( bFlipped ) { gamestats->Event_FlippedVehicle( player, driveable ); } m_bVehicleFlipped = bFlipped; } } else { m_bVehicleFlipped = false; } } else { m_bVehicleFlipped = false; distance = VectorLength( player->GetAbsOrigin() - m_vecSaveOrigin ); } if ( distance > 0 ) { gamestats->Event_PlayerTraveled( player, distance, pVehicle ? true : false, !pVehicle && static_cast< CHL2_Player * >( player )->IsSprinting() ); } } bool bGodMode = ( player->GetFlags() & FL_GODMODE ) ? true : false; if ( m_bInGodMode != bGodMode ) { m_bInGodMode = bGodMode; if ( bGodMode ) { gamestats->Event_PlayerEnteredGodMode( player ); } } bool bNoClip = ( player->GetMoveType() == MOVETYPE_NOCLIP ); if ( m_bInNoClip != bNoClip ) { m_bInNoClip = bNoClip; if ( bNoClip ) { gamestats->Event_PlayerEnteredNoClip( player ); } } }
//----------------------------------------------------------------------------- //----------------------------------------------------------------------------- void CRagdollProp::HandleFirstCollisionInteractions( int index, gamevcollisionevent_t *pEvent ) { IPhysicsObject *pObj = VPhysicsGetObject(); if ( !pObj) return; if( HasPhysgunInteraction( "onfirstimpact", "break" ) ) { // Looks like it's best to break by having the object damage itself. CTakeDamageInfo info; info.SetDamage( m_iHealth ); info.SetAttacker( this ); info.SetInflictor( this ); info.SetDamageType( DMG_GENERIC ); Vector vecPosition; Vector vecVelocity; VPhysicsGetObject()->GetVelocity( &vecVelocity, NULL ); VPhysicsGetObject()->GetPosition( &vecPosition, NULL ); info.SetDamageForce( vecVelocity ); info.SetDamagePosition( vecPosition ); TakeDamage( info ); return; } if( HasPhysgunInteraction( "onfirstimpact", "paintsplat" ) ) { IPhysicsObject *pObj = VPhysicsGetObject(); Vector vecPos; pObj->GetPosition( &vecPos, NULL ); trace_t tr; UTIL_TraceLine( vecPos, vecPos + pEvent->preVelocity[0] * 1.5, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); switch( random->RandomInt( 1, 3 ) ) { case 1: UTIL_DecalTrace( &tr, "PaintSplatBlue" ); break; case 2: UTIL_DecalTrace( &tr, "PaintSplatGreen" ); break; case 3: UTIL_DecalTrace( &tr, "PaintSplatPink" ); break; } } bool bAlienBloodSplat = HasPhysgunInteraction( "onfirstimpact", "alienbloodsplat" ); if( bAlienBloodSplat || HasPhysgunInteraction( "onfirstimpact", "bloodsplat" ) ) { IPhysicsObject *pObj = VPhysicsGetObject(); Vector vecPos; pObj->GetPosition( &vecPos, NULL ); trace_t tr; UTIL_TraceLine( vecPos, vecPos + pEvent->preVelocity[0] * 1.5, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); UTIL_BloodDecalTrace( &tr, bAlienBloodSplat ? BLOOD_COLOR_GREEN : BLOOD_COLOR_RED ); } }
//----------------------------------------------------------------------------- // Debugging methods //----------------------------------------------------------------------------- void CFourWheelVehiclePhysics::DrawDebugGeometryOverlays() { Vector vecRad(m_debugRadius,m_debugRadius,m_debugRadius); for ( int i = 0; i < m_wheelCount; i++ ) { NDebugOverlay::BoxAngles(m_wheelPosition[i], -vecRad, vecRad, m_wheelRotation[i], 0, 255, 45, 0 ,0); } for ( int iWheel = 0; iWheel < m_wheelCount; iWheel++ ) { IPhysicsObject *pWheel = m_pVehicle->GetWheel( iWheel ); Vector vecPos; QAngle vecRot; pWheel->GetPosition( &vecPos, &vecRot ); NDebugOverlay::BoxAngles( vecPos, -vecRad, vecRad, vecRot, 0, 255, 45, 0 ,0 ); } #if 1 // Render vehicle data. IPhysicsObject *pBody = m_pOuter->VPhysicsGetObject(); if ( pBody ) { const vehicleparams_t vehicleParams = m_pVehicle->GetVehicleParams(); // Draw a red cube as the "center" of the vehicle. Vector vecBodyPosition; QAngle angBodyDirection; pBody->GetPosition( &vecBodyPosition, &angBodyDirection ); NDebugOverlay::BoxAngles( vecBodyPosition, Vector( -5, -5, -5 ), Vector( 5, 5, 5 ), angBodyDirection, 255, 0, 0, 0 ,0 ); matrix3x4_t matrix; AngleMatrix( angBodyDirection, vecBodyPosition, matrix ); // Draw green cubes at axle centers. Vector vecAxlePositions[2], vecAxlePositionsHL[2]; vecAxlePositions[0] = vehicleParams.axles[0].offset; vecAxlePositions[1] = vehicleParams.axles[1].offset; VectorTransform( vecAxlePositions[0], matrix, vecAxlePositionsHL[0] ); VectorTransform( vecAxlePositions[1], matrix, vecAxlePositionsHL[1] ); NDebugOverlay::BoxAngles( vecAxlePositionsHL[0], Vector( -3, -3, -3 ), Vector( 3, 3, 3 ), angBodyDirection, 0, 255, 0, 0 ,0 ); NDebugOverlay::BoxAngles( vecAxlePositionsHL[1], Vector( -3, -3, -3 ), Vector( 3, 3, 3 ), angBodyDirection, 0, 255, 0, 0 ,0 ); // Draw blue cubes at wheel centers. Vector vecWheelPositions[4], vecWheelPositionsHL[4]; vecWheelPositions[0] = vehicleParams.axles[0].offset; vecWheelPositions[0] += vehicleParams.axles[0].wheelOffset; vecWheelPositions[1] = vehicleParams.axles[0].offset; vecWheelPositions[1] -= vehicleParams.axles[0].wheelOffset; vecWheelPositions[2] = vehicleParams.axles[1].offset; vecWheelPositions[2] += vehicleParams.axles[1].wheelOffset; vecWheelPositions[3] = vehicleParams.axles[1].offset; vecWheelPositions[3] -= vehicleParams.axles[1].wheelOffset; VectorTransform( vecWheelPositions[0], matrix, vecWheelPositionsHL[0] ); VectorTransform( vecWheelPositions[1], matrix, vecWheelPositionsHL[1] ); VectorTransform( vecWheelPositions[2], matrix, vecWheelPositionsHL[2] ); VectorTransform( vecWheelPositions[3], matrix, vecWheelPositionsHL[3] ); float flWheelRadius = vehicleParams.axles[0].wheels.radius; flWheelRadius = IVP2HL( flWheelRadius ); Vector vecWheelRadius( flWheelRadius, flWheelRadius, flWheelRadius ); NDebugOverlay::BoxAngles( vecWheelPositionsHL[0], -vecWheelRadius, vecWheelRadius, angBodyDirection, 0, 0, 255, 0 ,0 ); NDebugOverlay::BoxAngles( vecWheelPositionsHL[1], -vecWheelRadius, vecWheelRadius, angBodyDirection, 0, 0, 255, 0 ,0 ); NDebugOverlay::BoxAngles( vecWheelPositionsHL[2], -vecWheelRadius, vecWheelRadius, angBodyDirection, 0, 0, 255, 0 ,0 ); NDebugOverlay::BoxAngles( vecWheelPositionsHL[3], -vecWheelRadius, vecWheelRadius, angBodyDirection, 0, 0, 255, 0 ,0 ); // Draw wheel raycasts in yellow vehicle_debugcarsystem_t debugCarSystem; m_pVehicle->GetCarSystemDebugData( debugCarSystem ); for ( int iWheel = 0; iWheel < 4; ++iWheel ) { Vector vecStart, vecEnd, vecImpact; // Hack for now. float tmpY = IVP2HL( debugCarSystem.vecWheelRaycasts[iWheel][0].z ); vecStart.z = -IVP2HL( debugCarSystem.vecWheelRaycasts[iWheel][0].y ); vecStart.y = tmpY; vecStart.x = IVP2HL( debugCarSystem.vecWheelRaycasts[iWheel][0].x ); tmpY = IVP2HL( debugCarSystem.vecWheelRaycasts[iWheel][1].z ); vecEnd.z = -IVP2HL( debugCarSystem.vecWheelRaycasts[iWheel][1].y ); vecEnd.y = tmpY; vecEnd.x = IVP2HL( debugCarSystem.vecWheelRaycasts[iWheel][1].x ); tmpY = IVP2HL( debugCarSystem.vecWheelRaycastImpacts[iWheel].z ); vecImpact.z = -IVP2HL( debugCarSystem.vecWheelRaycastImpacts[iWheel].y ); vecImpact.y = tmpY; vecImpact.x = IVP2HL( debugCarSystem.vecWheelRaycastImpacts[iWheel].x ); NDebugOverlay::BoxAngles( vecStart, Vector( -1 , -1, -1 ), Vector( 1, 1, 1 ), angBodyDirection, 0, 255, 0, 0, 0 ); NDebugOverlay::Line( vecStart, vecEnd, 255, 255, 0, true, 0 ); NDebugOverlay::BoxAngles( vecEnd, Vector( -1, -1, -1 ), Vector( 1, 1, 1 ), angBodyDirection, 255, 0, 0, 0, 0 ); NDebugOverlay::BoxAngles( vecImpact, Vector( -0.5f , -0.5f, -0.5f ), Vector( 0.5f, 0.5f, 0.5f ), angBodyDirection, 0, 0, 255, 0, 0 ); } } #endif }