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 CDecal :: StaticDecal( void ) { trace_t trace; int entityIndex, modelIndex = 0; Vector position = GetAbsOrigin(); UTIL_TraceLine( position - Vector(5,5,5), position + Vector(5,5,5), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &trace ); entityIndex = (short)trace.m_pEnt ? trace.m_pEnt->entindex() : 0; if ( entityIndex ) { CBaseEntity *ent = trace.m_pEnt; if ( ent ) { modelIndex = ent->GetModelIndex(); VectorITransform( GetAbsOrigin(), ent->EntityToWorldTransform(), position ); } } engine->StaticDecal( position, m_nTexture, entityIndex, modelIndex ); // CRecipientFilter initFilter; // initFilter.MakeInitMessage(); // TE_BSPDecal( initFilter, GetAbsOrigin(), entityIndex, (int)pev->skin ); SUB_Remove(); }
// Converts world HL units to HL local/object units void CPhysicsObject::WorldToLocal( Vector &localPosition, const Vector &worldPosition ) { matrix3x4_t matrix; GetPositionMatrix( matrix ); // copy in case the src == dest VectorITransform( Vector(worldPosition), matrix, localPosition ); }
void CPhysicsObject::WorldToLocal(Vector *localPosition, const Vector &worldPosition) const { if (!localPosition) return; matrix3x4_t matrix; GetPositionMatrix(&matrix); VectorITransform(worldPosition, matrix, *localPosition); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- bool CFourWheelVehiclePhysics::VPhysicsUpdate( IPhysicsObject *pPhysics ) { if ( r_vehicleDrawDebug.GetInt() ) { DrawDebugGeometryOverlays(); } // must be a wheel if ( pPhysics == m_pOuter->VPhysicsGetObject() ) return true; // This is here so we can make the pose parameters of the wheels // reflect their current physics state for ( int i = 0; i < m_wheelCount; i++ ) { if ( pPhysics == m_pWheels[i] ) { Vector tmp; pPhysics->GetPosition( &m_wheelPosition[i], &m_wheelRotation[i] ); // transform the wheel into body space VectorITransform( m_wheelPosition[i], m_pOuter->EntityToWorldTransform(), tmp ); SetPoseParameter( m_poseParameters[VEH_FL_WHEEL_HEIGHT + i], (m_wheelBaseHeight[i] - tmp.z) / m_wheelTotalHeight[i] ); SetPoseParameter( m_poseParameters[VEH_FL_WHEEL_SPIN + i], -m_wheelRotation[i].z ); return false; } } return false; }
//----------------------------------------------------------------------------- // Purpose: Update the driver's gun //----------------------------------------------------------------------------- void CBaseTFVehicle::VehicleDriverGunThink( void ) { if ( !m_hDriverGun ) return; // No driver? CBaseTFPlayer *pDriver = GetDriverPlayer(); if ( !pDriver ) return; QAngle vecTargetAngles = m_hDriverGun->GetCurrentAngles(); // Cast a ray out of the view to see where the player is looking. trace_t trace; Vector vecForward; Vector vecSrc; QAngle angEyeAngles; GetVehicleViewPosition( VEHICLE_DRIVER, &vecSrc, &angEyeAngles, NULL ); AngleVectors( angEyeAngles, &vecForward, NULL, NULL ); Vector vecEnd = vecSrc + (vecForward * 10000); UTIL_TraceLine( vecSrc, vecEnd, MASK_OPAQUE, this, COLLISION_GROUP_NONE, &trace ); //NDebugOverlay::Box( vecSrc, -Vector(10,10,10), Vector(10,10,10), 255,0,0,8, 5 ); //NDebugOverlay::Box( vecEnd, -Vector(10,10,10), Vector(10,10,10), 0,255,0,8, 5 ); //NDebugOverlay::Box( trace.endpos, -Vector(10,10,10), Vector(10,10,10), 255,255,255,8, 0.1 ); if ( trace.fraction < 1 ) { // Figure out what angles our turret needs to be at in order to hit the target. Vector vFireOrigin = m_hDriverGun->GetFireOrigin(); //NDebugOverlay::Box( vFireOrigin, -Vector(10,10,10), Vector(10,10,10), 0,255,0,8, 0.1 ); // Get a direction vector that points at the target. Vector vTo = trace.endpos - vFireOrigin; // Transform it into the tank's local space. matrix3x4_t tankToWorld; AngleMatrix( GetAbsAngles(), tankToWorld ); Vector vLocalTo; VectorITransform( vTo, tankToWorld, vLocalTo ); // Now figure out what the angles are in local space. QAngle localAngles; VectorAngles( vLocalTo, localAngles ); vecTargetAngles[YAW] = localAngles[YAW] - 90; vecTargetAngles[PITCH] = anglemod( localAngles[PITCH] ); } // Set the gun's angles m_hDriverGun->SetTargetAngles( vecTargetAngles ); }
void QUA_helicopter::Activate() { BaseClass::Activate(); m_nGunBaseAttachment = LookupAttachment("gun"); m_nMachineGunMuzzleAttachment = LookupAttachment( "muzzle" ); m_nBombAttachment=LookupAttachment("Bomb"); Vector vecWorldBarrelPos; QAngle worldBarrelAngle; matrix3x4_t matRefToWorld; GetAttachment( m_nMachineGunMuzzleAttachment, vecWorldBarrelPos, worldBarrelAngle ); GetAttachment(m_nGunBaseAttachment, matRefToWorld ); VectorITransform( vecWorldBarrelPos, matRefToWorld, m_vecBarrelPos ); }
const Vector &CECollisionProperty::WorldToCollisionSpace( const Vector &in, Vector *pResult ) const { if ( !IsBoundsDefinedInEntitySpace() || ( GetCollisionAngles() == vec3_angle ) ) { VectorSubtract( in, GetCollisionOrigin(), *pResult ); } else { VectorITransform( in, CollisionToWorldTransform(), *pResult ); } return *pResult; }
void TransformVertex(MS3D *ms3d, const ms3d_vertex_t *vertex, float *out) { int jointIndices[4], jointWeights[4]; FillJointIndicesAndWeights(vertex, jointIndices, jointWeights); if (jointIndices[0] < 0 || jointIndices[0] >= ms3d->nNumJoints || ms3d->fCurrentTime < 0.0f) { out[0] = vertex->vertex[0]; out[1] = vertex->vertex[1]; out[2] = vertex->vertex[2]; } else { // count valid weights int numWeights = 0; int i; for (i = 0; i < 4; i++) { if ((jointWeights[i] > 0) && (jointIndices[i] >= 0) && (jointIndices[i] < ms3d->nNumJoints) ) ++numWeights; else break; } // init out[0] = 0.0f; out[1] = 0.0f; out[2] = 0.0f; float weights[4] = { (float) jointWeights[0] / 100.0f, (float) jointWeights[1] / 100.0f, (float) jointWeights[2] / 100.0f, (float) jointWeights[3] / 100.0f }; if (numWeights == 0) { numWeights = 1; weights[0] = 1.0f; } // add weighted vertices for (i = 0; i < numWeights; i++) { //const ms3d_joint_t *joint = &m_joints[jointIndices[i]]; const ms3d_joint_t *joint = &ms3d->joints[jointIndices[i]]; vec3_t tmp, vert; //VectorITransform(vertex->vertex, joint->matGlobalSkeleton, tmp); VectorITransform(vertex->vertex, (void *) ms3d->joints[jointIndices[i]].matGlobalSkeleton, tmp); VectorTransform(tmp, (void *) ms3d->joints[jointIndices[i]].matGlobal, vert); out[0] += vert[0] * weights[i]; out[1] += vert[1] * weights[i]; out[2] += vert[2] * weights[i]; printf("%f, %f, %f\n", ms3d->joints[jointIndices[i]].matGlobalSkeleton[1][0], ms3d->joints[jointIndices[i]].matGlobalSkeleton[1][1], ms3d->joints[jointIndices[i]].matGlobalSkeleton[1][2] ); //printf("%f, %f, %f\n", tmp[0], tmp[1], tmp[2]); //printf("%f, %f, %f\n", vert[0], vert[1], vert[2]); //printf("%f\n", weights[i]); } } }
void msModel::TransformVertex(const ms3d_vertex_t *vertex, vec3_t out) const { int jointIndices[4], jointWeights[4]; FillJointIndicesAndWeights(vertex, jointIndices, jointWeights); if (jointIndices[0] < 0 || jointIndices[0] >= (int) m_joints.size() || m_currentTime < 0.0f) { out[0] = vertex->vertex[0]; out[1] = vertex->vertex[1]; out[2] = vertex->vertex[2]; } else { // count valid weights int numWeights = 0; for (int i = 0; i < 4; i++) { if (jointWeights[i] > 0 && jointIndices[i] >= 0 && jointIndices[i] < (int) m_joints.size()) ++numWeights; else break; } // init out[0] = 0.0f; out[1] = 0.0f; out[2] = 0.0f; float weights[4] = { (float) jointWeights[0] / 100.0f, (float) jointWeights[1] / 100.0f, (float) jointWeights[2] / 100.0f, (float) jointWeights[3] / 100.0f }; if (numWeights == 0) { numWeights = 1; weights[0] = 1.0f; } // add weighted vertices for (int i = 0; i < numWeights; i++) { const ms3d_joint_t *joint = &m_joints[jointIndices[i]]; vec3_t tmp, vert; VectorITransform(vertex->vertex, joint->matGlobalSkeleton, tmp); VectorTransform(tmp, joint->matGlobal, vert); out[0] += vert[0] * weights[i]; out[1] += vert[1] * weights[i]; out[2] += vert[2] * weights[i]; } } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CPropAPC::Activate() { BaseClass::Activate(); m_nRocketAttachment = LookupAttachment( "cannon_muzzle" ); m_nMachineGunMuzzleAttachment = LookupAttachment( "muzzle" ); m_nMachineGunBaseAttachment = LookupAttachment( "gun_base" ); // NOTE: gun_ref must have the same position as gun_base, but rotates with the gun int nMachineGunRefAttachment = LookupAttachment( "gun_def" ); Vector vecWorldBarrelPos; matrix3x4_t matRefToWorld; GetAttachment( m_nMachineGunMuzzleAttachment, vecWorldBarrelPos ); GetAttachment( nMachineGunRefAttachment, matRefToWorld ); VectorITransform( vecWorldBarrelPos, matRefToWorld, m_vecBarrelPos ); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void C_NPC_Barnacle::StandardBlendingRules( Vector pos[], Quaternion q[], float currentTime, int boneMask ) { BaseClass::StandardBlendingRules( pos, q, currentTime, boneMask ); // Don't do anything while dead if ( !IsAlive() ) return; studiohdr_t *hdr = GetModelPtr(); if ( !hdr ) return; int firstBone = Studio_BoneIndexByName( hdr, "Barnacle.tongue1" ); Vector vecPrev = pos[firstBone-1]; Vector vecCurr = vec3_origin; for ( int i = 0; i <= BARNACLE_TONGUE_POINTS; i++ ) { // We double up the bones at the last node. Vector vecCurr; if ( i == BARNACLE_TONGUE_POINTS ) { vecCurr = m_TonguePhysics.GetLastNode()->m_vPos; } else { vecCurr = m_TonguePhysics.GetNode(i)->m_vPos; } //debugoverlay->AddBoxOverlay( vecCurr, -Vector(2,2,2), Vector(2,2,2), vec3_angle, 0,255,0, 128, 0.1 ); // Fill out the positions in local space VectorITransform( vecCurr, EntityToWorldTransform(), pos[firstBone+i] ); vecCurr = pos[firstBone+i]; // Fill out the angles Vector vecForward = (vecCurr - vecPrev); VectorNormalize( vecForward ); QAngle vecAngle; VectorAngles( vecForward, vecAngle ); AngleQuaternion( vecAngle, q[firstBone+i] ); vecPrev = vecCurr; } }
void CDecal::StaticDecal( void ) { Vector position; CBaseEntity *pEntity = GetDecalEntityAndPosition(&position, true); int entityIndex = 0; int modelIndex = 0; if ( pEntity ) { entityIndex = pEntity->entindex(); modelIndex = pEntity->GetModelIndex(); Vector worldspace = position; VectorITransform( worldspace, pEntity->EntityToWorldTransform(), position ); } else { position = GetAbsOrigin(); } engine->StaticDecal( position, m_nTexture, entityIndex, modelIndex, m_bLowPriority ); SUB_Remove(); }
void C_EnvProjectedTexture::UpdateLight( void ) { VPROF("C_EnvProjectedTexture::UpdateLight"); bool bVisible = true; Vector vLinearFloatLightColor( m_LightColor.r, m_LightColor.g, m_LightColor.b ); float flLinearFloatLightAlpha = m_LightColor.a; if ( m_bAlwaysUpdate ) { m_bForceUpdate = true; } if ( m_CurrentLinearFloatLightColor != vLinearFloatLightColor || m_flCurrentLinearFloatLightAlpha != flLinearFloatLightAlpha ) { float flColorTransitionSpeed = gpGlobals->frametime * m_flColorTransitionTime * 255.0f; m_CurrentLinearFloatLightColor.x = Approach( vLinearFloatLightColor.x, m_CurrentLinearFloatLightColor.x, flColorTransitionSpeed ); m_CurrentLinearFloatLightColor.y = Approach( vLinearFloatLightColor.y, m_CurrentLinearFloatLightColor.y, flColorTransitionSpeed ); m_CurrentLinearFloatLightColor.z = Approach( vLinearFloatLightColor.z, m_CurrentLinearFloatLightColor.z, flColorTransitionSpeed ); m_flCurrentLinearFloatLightAlpha = Approach( flLinearFloatLightAlpha, m_flCurrentLinearFloatLightAlpha, flColorTransitionSpeed ); m_bForceUpdate = true; } if ( !m_bForceUpdate ) { bVisible = IsBBoxVisible(); } if ( m_bState == false || !bVisible ) { // Spotlight's extents aren't in view ShutDownLightHandle(); return; } if ( m_LightHandle == CLIENTSHADOW_INVALID_HANDLE || m_hTargetEntity != NULL || m_bForceUpdate ) { Vector vForward, vRight, vUp, vPos = GetAbsOrigin(); FlashlightState_t state; if ( m_hTargetEntity != NULL ) { if ( m_bCameraSpace ) { const QAngle &angles = GetLocalAngles(); C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); if( pPlayer ) { const QAngle playerAngles = pPlayer->GetAbsAngles(); Vector vPlayerForward, vPlayerRight, vPlayerUp; AngleVectors( playerAngles, &vPlayerForward, &vPlayerRight, &vPlayerUp ); matrix3x4_t mRotMatrix; AngleMatrix( angles, mRotMatrix ); VectorITransform( vPlayerForward, mRotMatrix, vForward ); VectorITransform( vPlayerRight, mRotMatrix, vRight ); VectorITransform( vPlayerUp, mRotMatrix, vUp ); float dist = (m_hTargetEntity->GetAbsOrigin() - GetAbsOrigin()).Length(); vPos = m_hTargetEntity->GetAbsOrigin() - vForward*dist; VectorNormalize( vForward ); VectorNormalize( vRight ); VectorNormalize( vUp ); } } else { vForward = m_hTargetEntity->GetAbsOrigin() - GetAbsOrigin(); VectorNormalize( vForward ); // JasonM - unimplemented Assert (0); //Quaternion q = DirectionToOrientation( dir ); // // JasonM - set up vRight, vUp // // VectorNormalize( vRight ); // VectorNormalize( vUp ); } } else { AngleVectors( GetAbsAngles(), &vForward, &vRight, &vUp ); } state.m_fHorizontalFOVDegrees = m_flLightFOV; state.m_fVerticalFOVDegrees = m_flLightFOV; state.m_vecLightOrigin = vPos; BasisToQuaternion( vForward, vRight, vUp, state.m_quatOrientation ); state.m_NearZ = m_flNearZ; state.m_FarZ = m_flFarZ; // quickly check the proposed light's bbox against the view frustum to determine whether we // should bother to create it, if it doesn't exist, or cull it, if it does. if ( m_bSimpleProjection == false ) { #pragma message("OPTIMIZATION: this should be made SIMD") // get the half-widths of the near and far planes, // based on the FOV which is in degrees. Remember that // on planet Valve, x is forward, y left, and z up. const float tanHalfAngle = tan( m_flLightFOV * ( M_PI/180.0f ) * 0.5f ); const float halfWidthNear = tanHalfAngle * m_flNearZ; const float halfWidthFar = tanHalfAngle * m_flFarZ; // now we can build coordinates in local space: the near rectangle is eg // (0, -halfWidthNear, -halfWidthNear), (0, halfWidthNear, -halfWidthNear), // (0, halfWidthNear, halfWidthNear), (0, -halfWidthNear, halfWidthNear) VectorAligned vNearRect[4] = { VectorAligned( m_flNearZ, -halfWidthNear, -halfWidthNear), VectorAligned( m_flNearZ, halfWidthNear, -halfWidthNear), VectorAligned( m_flNearZ, halfWidthNear, halfWidthNear), VectorAligned( m_flNearZ, -halfWidthNear, halfWidthNear) }; VectorAligned vFarRect[4] = { VectorAligned( m_flFarZ, -halfWidthFar, -halfWidthFar), VectorAligned( m_flFarZ, halfWidthFar, -halfWidthFar), VectorAligned( m_flFarZ, halfWidthFar, halfWidthFar), VectorAligned( m_flFarZ, -halfWidthFar, halfWidthFar) }; matrix3x4_t matOrientation( vForward, -vRight, vUp, vPos ); enum { kNEAR = 0, kFAR = 1, }; VectorAligned vOutRects[2][4]; for ( int i = 0 ; i < 4 ; ++i ) { VectorTransform( vNearRect[i].Base(), matOrientation, vOutRects[0][i].Base() ); } for ( int i = 0 ; i < 4 ; ++i ) { VectorTransform( vFarRect[i].Base(), matOrientation, vOutRects[1][i].Base() ); } // now take the MIN and MAX extents for the bbox, and see if it is visible. Vector mins = **vOutRects; Vector maxs = **vOutRects; for ( int i = 1; i < 8 ; ++i ) { VectorMin( mins, *(*vOutRects+i), mins ); VectorMax( maxs, *(*vOutRects+i), maxs ); } #if 0 //for debugging the visibility frustum we just calculated NDebugOverlay::Triangle( vOutRects[0][0], vOutRects[0][1], vOutRects[0][2], 255, 0, 0, 100, true, 0.0f ); //first tri NDebugOverlay::Triangle( vOutRects[0][2], vOutRects[0][1], vOutRects[0][0], 255, 0, 0, 100, true, 0.0f ); //make it double sided NDebugOverlay::Triangle( vOutRects[0][2], vOutRects[0][3], vOutRects[0][0], 255, 0, 0, 100, true, 0.0f ); //second tri NDebugOverlay::Triangle( vOutRects[0][0], vOutRects[0][3], vOutRects[0][2], 255, 0, 0, 100, true, 0.0f ); //make it double sided NDebugOverlay::Triangle( vOutRects[1][0], vOutRects[1][1], vOutRects[1][2], 0, 0, 255, 100, true, 0.0f ); //first tri NDebugOverlay::Triangle( vOutRects[1][2], vOutRects[1][1], vOutRects[1][0], 0, 0, 255, 100, true, 0.0f ); //make it double sided NDebugOverlay::Triangle( vOutRects[1][2], vOutRects[1][3], vOutRects[1][0], 0, 0, 255, 100, true, 0.0f ); //second tri NDebugOverlay::Triangle( vOutRects[1][0], vOutRects[1][3], vOutRects[1][2], 0, 0, 255, 100, true, 0.0f ); //make it double sided NDebugOverlay::Box( vec3_origin, mins, maxs, 0, 255, 0, 100, 0.0f ); #endif bool bVisible = IsBBoxVisible( mins, maxs ); if (!bVisible) { // Spotlight's extents aren't in view if ( m_LightHandle != CLIENTSHADOW_INVALID_HANDLE ) { ShutDownLightHandle(); } return; } } float flAlpha = m_flCurrentLinearFloatLightAlpha * ( 1.0f / 255.0f ); state.m_fQuadraticAtten = 0.0; state.m_fLinearAtten = 100; state.m_fConstantAtten = 0.0f; state.m_FarZAtten = m_flFarZ; state.m_fBrightnessScale = m_flBrightnessScale; state.m_Color[0] = m_CurrentLinearFloatLightColor.x * ( 1.0f / 255.0f ) * flAlpha; state.m_Color[1] = m_CurrentLinearFloatLightColor.y * ( 1.0f / 255.0f ) * flAlpha; state.m_Color[2] = m_CurrentLinearFloatLightColor.z * ( 1.0f / 255.0f ) * flAlpha; state.m_Color[3] = 0.0f; // fixme: need to make ambient work m_flAmbient; state.m_flShadowSlopeScaleDepthBias = g_pMaterialSystemHardwareConfig->GetShadowSlopeScaleDepthBias(); state.m_flShadowDepthBias = g_pMaterialSystemHardwareConfig->GetShadowDepthBias(); state.m_bEnableShadows = m_bEnableShadows; state.m_pSpotlightTexture = m_SpotlightTexture; state.m_pProjectedMaterial = NULL; // only complain if we're using material projection state.m_nSpotlightTextureFrame = m_nSpotlightTextureFrame; state.m_flProjectionSize = m_flProjectionSize; state.m_flProjectionRotation = m_flRotation; state.m_nShadowQuality = m_nShadowQuality; // Allow entity to affect shadow quality if ( m_bSimpleProjection == true ) { state.m_bSimpleProjection = true; state.m_bOrtho = true; state.m_fOrthoLeft = -m_flProjectionSize; state.m_fOrthoTop = -m_flProjectionSize; state.m_fOrthoRight = m_flProjectionSize; state.m_fOrthoBottom = m_flProjectionSize; } if( m_LightHandle == CLIENTSHADOW_INVALID_HANDLE ) { // Hack: env projected textures don't work like normal flashlights; they're not assigned to a given splitscreen slot, // but the flashlight code requires this HACK_GETLOCALPLAYER_GUARD( "Env projected texture" ); if ( m_bSimpleProjection == true ) { m_LightHandle = g_pClientShadowMgr->CreateProjection( state ); } else { m_LightHandle = g_pClientShadowMgr->CreateFlashlight( state ); } if ( m_LightHandle != CLIENTSHADOW_INVALID_HANDLE ) { m_bForceUpdate = false; } } else { if ( m_bSimpleProjection == true ) { g_pClientShadowMgr->UpdateProjectionState( m_LightHandle, state ); } else { g_pClientShadowMgr->UpdateFlashlightState( m_LightHandle, state ); } m_bForceUpdate = false; } g_pClientShadowMgr->GetFrustumExtents( m_LightHandle, m_vecExtentsMin, m_vecExtentsMax ); m_vecExtentsMin = m_vecExtentsMin - GetAbsOrigin(); m_vecExtentsMax = m_vecExtentsMax - GetAbsOrigin(); } if( m_bLightOnlyTarget ) { g_pClientShadowMgr->SetFlashlightTarget( m_LightHandle, m_hTargetEntity ); } else { g_pClientShadowMgr->SetFlashlightTarget( m_LightHandle, NULL ); } g_pClientShadowMgr->SetFlashlightLightWorld( m_LightHandle, m_bLightWorld ); if ( !asw_perf_wtf.GetBool() && !m_bForceUpdate ) { g_pClientShadowMgr->UpdateProjectedTexture( m_LightHandle, true ); } }
void IFaceposerModels::CFacePoserModel::CreateNewBitmap( char const *pchBitmapFilename, int sequence, int nSnapShotSize, bool bZoomInOnFace, CExpression *pExpression, mxbitmapdata_t *bitmap ) { MatSysWindow *pWnd = g_pMatSysWindow; if ( !pWnd ) return; StudioModel *model = m_pModel; if ( !model ) return; CStudioHdr *hdr = model->GetStudioHdr(); if ( !hdr ) return; if ( sequence < 0 || sequence >= hdr->GetNumSeq() ) return; mstudioseqdesc_t &seqdesc = hdr->pSeqdesc( sequence ); Con_ColorPrintf( FILE_COLOR, "Creating bitmap %s for sequence '%s'\n", pchBitmapFilename, seqdesc.pszLabel() ); model->ClearOverlaysSequences(); int iLayer = model->GetNewAnimationLayer(); model->SetOverlaySequence( iLayer, sequence, 1.0 ); model->SetOverlayRate( iLayer, FindPoseCycle( model, sequence ), 0.0 ); for (int i = 0; i < hdr->GetNumPoseParameters(); i++) { model->SetPoseParameter( i, 0.0 ); } float flexValues[ GLOBAL_STUDIO_FLEX_CONTROL_COUNT ] = { 0 }; if ( pExpression ) { float *settings = pExpression->GetSettings(); float *weights = pExpression->GetWeights(); // Save existing settings from model for ( LocalFlexController_t i = LocalFlexController_t(0); i < hdr->numflexcontrollers(); ++i ) { int j = hdr->pFlexcontroller( i )->localToGlobal; if ( j == -1 ) continue; flexValues[ i ] = model->GetFlexController( i ); // Set Value from passed in settings model->SetFlexController( i, settings[ j ] * weights[ j ] ); } } model->ClearLookTargets( ); QAngle oldrot, oldLight; Vector oldtrans; VectorCopy( model->m_angles, oldrot ); VectorCopy( model->m_origin, oldtrans ); VectorCopy( g_viewerSettings.lightrot, oldLight ); model->m_angles.Init(); model->m_origin.Init(); g_viewerSettings.lightrot.Init(); g_viewerSettings.lightrot.y = -180; bool bSaveGround = g_viewerSettings.showGround; g_viewerSettings.showGround = false; if ( bZoomInOnFace ) { Vector size; VectorSubtract( hdr->hull_max(), hdr->hull_min(), size ); float eyeheight = hdr->hull_min().z + 0.9 * size.z; // float width = ( size.x + size.y ) / 2.0f; model->m_origin.x = size.z * .6f; if ( hdr->GetNumAttachments() > 0 ) { for (int i = 0; i < hdr->GetNumAttachments(); i++) { const mstudioattachment_t &attachment = hdr->pAttachment( i ); int iBone = hdr->GetAttachmentBone( i ); if ( Q_stricmp( attachment.pszName(), "eyes" ) ) continue; mstudiobone_t *bone = hdr->pBone( iBone ); if ( !bone ) continue; matrix3x4_t boneToPose; MatrixInvert( bone->poseToBone, boneToPose ); matrix3x4_t attachmentPoseToLocal; ConcatTransforms( boneToPose, attachment.local, attachmentPoseToLocal ); Vector localSpaceEyePosition; VectorITransform( vec3_origin, attachmentPoseToLocal, localSpaceEyePosition ); // Not sure why this must be negative? eyeheight = -localSpaceEyePosition.z + hdr->hull_min().z; break; } } KeyValues *seqKeyValues = new KeyValues(""); if ( seqKeyValues->LoadFromBuffer( model->GetFileName( ), model->GetKeyValueText( sequence ) ) ) { // Do we have a build point section? KeyValues *pkvAllFaceposer = seqKeyValues->FindKey("faceposer"); if ( pkvAllFaceposer ) { float flEyeheight = pkvAllFaceposer->GetFloat( "eye_height", -9999.0f ); if ( flEyeheight != -9999.0f ) { eyeheight = flEyeheight; } } } model->m_origin.z += eyeheight; } else { Vector mins, maxs; model->ExtractBbox(mins, maxs); Vector size; VectorSubtract( maxs, mins, size ); float maxdim = size.x; if ( size.y > maxdim ) maxdim = size.y; if ( size.z > maxdim ) maxdim = size.z; float midpoint = mins.z + 0.5 * size.z; model->m_origin.x = 3 * maxdim; model->m_origin.z += midpoint; } pWnd->SuppressResize( true ); RECT rcClient; HWND wnd = (HWND)pWnd->getHandle(); WINDOWPLACEMENT wp; GetWindowPlacement( wnd, &wp ); GetClientRect( wnd, &rcClient ); MoveWindow( wnd, 0, 0, nSnapShotSize + 16, nSnapShotSize + 16, TRUE ); // Snapshots are taken of the back buffer; // we need to render to the back buffer but not move it to the front pWnd->SuppressBufferSwap( true ); pWnd->redraw(); pWnd->SuppressBufferSwap( false ); // make it square, assumes w > h char fullpath[ 512 ]; Q_snprintf( fullpath, sizeof( fullpath ), "%s%s", GetGameDirectory(), pchBitmapFilename ); pWnd->TakeSnapshotRect( fullpath, 0, 0, nSnapShotSize, nSnapShotSize ); // Move back to original position SetWindowPlacement( wnd, &wp ); pWnd->SuppressResize( false ); VectorCopy( oldrot, model->m_angles ); VectorCopy( oldtrans, model->m_origin ); VectorCopy( oldLight, g_viewerSettings.lightrot ); g_viewerSettings.showGround = bSaveGround; if ( pExpression ) { // Save existing settings from model for ( LocalFlexController_t i = LocalFlexController_t(0); i < hdr->numflexcontrollers(); ++i ) { int j = hdr->pFlexcontroller( i )->localToGlobal; if ( j == -1 ) continue; model->SetFlexController( i, flexValues[ i ] ); } } model->ClearOverlaysSequences(); if ( bitmap->valid ) { DeleteObject( bitmap->image ); bitmap->image = 0; bitmap->valid = false; } LoadBitmapFromFile( pchBitmapFilename, *bitmap ); }
CTraceFilterValidForDecal traceFilter( this, COLLISION_GROUP_NONE ); int entityIndex, modelIndex = 0; Vector position = GetAbsOrigin(); UTIL_TraceLine( position - Vector(5,5,5), position + Vector(5,5,5), MASK_SOLID, &traceFilter, &trace ); bool canDraw = true; entityIndex = trace.m_pEnt ? (short)trace.m_pEnt->entindex() : 0; if ( entityIndex ) { CBaseEntity *ent = trace.m_pEnt; if ( ent ) { modelIndex = ent->GetModelIndex(); VectorITransform( GetAbsOrigin(), ent->EntityToWorldTransform(), position ); canDraw = ( modelIndex != 0 ); if ( !canDraw ) { Warning( "Suppressed StaticDecal which would have hit entity %i (class:%s, name:%s) with modelindex = 0\n", ent->entindex(), ent->GetClassname(), STRING( ent->GetEntityName() ) ); } } } if ( canDraw ) { engine->StaticDecal( position, m_nTexture, entityIndex, modelIndex, m_bLowPriority );
//----------------------------------------------------------------------------- // Purpose: Aim Gun at a target //----------------------------------------------------------------------------- void CASW_PropJeep::AimGunAt( Vector *endPos, float flInterval ) { Vector aimPos = *endPos; // See if the gun should be allowed to aim if ( IsOverturned() || m_bEngineLocked || m_bHasGun == false ) { SetPoseParameter( JEEP_GUN_YAW, 0 ); SetPoseParameter( JEEP_GUN_PITCH, 0 ); SetPoseParameter( JEEP_GUN_SPIN, 0 ); return; // Make the gun go limp and look "down" Vector v_forward, v_up; AngleVectors( GetLocalAngles(), NULL, &v_forward, &v_up ); aimPos = WorldSpaceCenter() + ( v_forward * -32.0f ) - Vector( 0, 0, 128.0f ); } matrix3x4_t gunMatrix; GetAttachment( LookupAttachment("gun_ref"), gunMatrix ); // transform the enemy into gun space Vector localEnemyPosition; VectorITransform( aimPos, gunMatrix, localEnemyPosition ); // do a look at in gun space (essentially a delta-lookat) QAngle localEnemyAngles; VectorAngles( localEnemyPosition, localEnemyAngles ); // convert to +/- 180 degrees localEnemyAngles.x = UTIL_AngleDiff( localEnemyAngles.x, 0 ); localEnemyAngles.y = UTIL_AngleDiff( localEnemyAngles.y, 0 ); float targetYaw = m_aimYaw + localEnemyAngles.y; float targetPitch = m_aimPitch + localEnemyAngles.x; // Constrain our angles float newTargetYaw = clamp( targetYaw, -CANNON_MAX_LEFT_YAW, CANNON_MAX_RIGHT_YAW ); float newTargetPitch = clamp( targetPitch, -CANNON_MAX_DOWN_PITCH, CANNON_MAX_UP_PITCH ); // If the angles have been clamped, we're looking outside of our valid range if ( fabs(newTargetYaw-targetYaw) > 1e-4 || fabs(newTargetPitch-targetPitch) > 1e-4 ) { m_bUnableToFire = true; } targetYaw = newTargetYaw; targetPitch = newTargetPitch; // Exponentially approach the target float yawSpeed = 8; float pitchSpeed = 8; m_aimYaw = UTIL_Approach( targetYaw, m_aimYaw, yawSpeed ); m_aimPitch = UTIL_Approach( targetPitch, m_aimPitch, pitchSpeed ); SetPoseParameter( JEEP_GUN_YAW, -m_aimYaw); SetPoseParameter( JEEP_GUN_PITCH, -m_aimPitch ); InvalidateBoneCache(); // read back to avoid drift when hitting limits // as long as the velocity is less than the delta between the limit and 180, this is fine. m_aimPitch = -GetPoseParameter( JEEP_GUN_PITCH ); m_aimYaw = -GetPoseParameter( JEEP_GUN_YAW ); // Now draw crosshair for actual aiming point Vector vecMuzzle, vecMuzzleDir; QAngle vecMuzzleAng; GetAttachment( "Muzzle", vecMuzzle, vecMuzzleAng ); AngleVectors( vecMuzzleAng, &vecMuzzleDir ); trace_t tr; UTIL_TraceLine( vecMuzzle, vecMuzzle + (vecMuzzleDir * MAX_TRACE_LENGTH), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); // see if we hit something, if so, adjust endPos to hit location if ( tr.fraction < 1.0 ) { m_vecGunCrosshair = vecMuzzle + ( vecMuzzleDir * MAX_TRACE_LENGTH * tr.fraction ); } }
void ControlPanel::CenterOnFace( void ) { if ( !models->GetActiveStudioModel() ) return; StudioModel *mdl = models->GetActiveStudioModel(); if ( !mdl ) return; CStudioHdr *hdr = mdl->GetStudioHdr(); if ( !hdr ) return; setSpeed( 1.0f ); int oldSeq = models->GetActiveStudioModel()->GetSequence(); int seq = models->GetActiveStudioModel()->LookupSequence( "idle_suble" ); if ( seq == -1 ) seq = 0; if ( seq != oldSeq ) { Con_Printf( "Centering changed model sequence # to %d\n", seq ); } setSequence( seq ); initPoseParameters( ); mdl->m_angles.Init(); mdl->m_origin.Init(); Vector size; VectorSubtract( hdr->hull_max(), hdr->hull_min(), size ); float eyeheight = hdr->hull_min().z + 0.9 * size.z; if ( hdr->GetNumAttachments() > 0 ) { for (int i = 0; i < hdr->GetNumAttachments(); i++) { const mstudioattachment_t &attachment = hdr->pAttachment( i ); int iBone = hdr->GetAttachmentBone( i ); if ( Q_stricmp( attachment.pszName(), "eyes" ) ) continue; mstudiobone_t *bone = hdr->pBone( iBone ); if ( !bone ) continue; matrix3x4_t boneToPose; MatrixInvert( bone->poseToBone, boneToPose ); matrix3x4_t attachmentPoseToLocal; ConcatTransforms( boneToPose, attachment.local, attachmentPoseToLocal ); Vector localSpaceEyePosition; VectorITransform( vec3_origin, attachmentPoseToLocal, localSpaceEyePosition ); // Not sure why this must be negative? eyeheight = -localSpaceEyePosition.z + hdr->hull_min().z; break; } } KeyValues *seqKeyValues = new KeyValues(""); if ( seqKeyValues->LoadFromBuffer( mdl->GetFileName( ), mdl->GetKeyValueText( seq ) ) ) { // Do we have a build point section? KeyValues *pkvAllFaceposer = seqKeyValues->FindKey("faceposer"); if ( pkvAllFaceposer ) { float flEyeheight = pkvAllFaceposer->GetFloat( "eye_height", -9999.0f ); if ( flEyeheight != -9999.0f ) { eyeheight = flEyeheight; } } } seqKeyValues->deleteThis(); mdl->m_origin.x = size.z * .65f; mdl->m_origin.z += eyeheight; CUtlVector< StudioModel * > modellist; modellist.AddToTail( models->GetActiveStudioModel() ); int i; if ( models->CountVisibleModels() > 0 ) { modellist.RemoveAll(); for ( i = 0; i < models->Count(); i++ ) { if ( models->IsModelShownIn3DView( i ) ) { modellist.AddToTail( models->GetStudioModel( i ) ); } } } int modelcount = modellist.Count(); int countover2 = modelcount / 2; int ydelta = GetModelGap(); int yoffset = -countover2 * ydelta; for ( i = 0 ; i < modelcount; i++ ) { if ( models->GetStudioHeader( i ) == hdr ) { mdl->m_origin.y = -yoffset; } yoffset += ydelta; } g_pMatSysWindow->redraw(); }
void C_EnvProjectedTexture::UpdateLight( bool bForceUpdate ) { if ( m_bState == false ) { if ( m_LightHandle != CLIENTSHADOW_INVALID_HANDLE ) { ShutDownLightHandle(); } return; } Vector vForward, vRight, vUp, vPos = GetAbsOrigin(); FlashlightState_t state; if ( m_hTargetEntity != NULL ) { if ( m_bCameraSpace ) { const QAngle &angles = GetLocalAngles(); C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); if( pPlayer ) { const QAngle playerAngles = pPlayer->GetAbsAngles(); Vector vPlayerForward, vPlayerRight, vPlayerUp; AngleVectors( playerAngles, &vPlayerForward, &vPlayerRight, &vPlayerUp ); matrix3x4_t mRotMatrix; AngleMatrix( angles, mRotMatrix ); VectorITransform( vPlayerForward, mRotMatrix, vForward ); VectorITransform( vPlayerRight, mRotMatrix, vRight ); VectorITransform( vPlayerUp, mRotMatrix, vUp ); float dist = (m_hTargetEntity->GetAbsOrigin() - GetAbsOrigin()).Length(); vPos = m_hTargetEntity->GetAbsOrigin() - vForward*dist; VectorNormalize( vForward ); VectorNormalize( vRight ); VectorNormalize( vUp ); } } else { // VXP: Fixing targeting Vector vecToTarget; QAngle vecAngles; if ( m_hTargetEntity == NULL ) { vecAngles = GetAbsAngles(); } else { vecToTarget = m_hTargetEntity->GetAbsOrigin() - GetAbsOrigin(); VectorAngles( vecToTarget, vecAngles ); } AngleVectors( vecAngles, &vForward, &vRight, &vUp ); } } else { AngleVectors( GetAbsAngles(), &vForward, &vRight, &vUp ); } state.m_fHorizontalFOVDegrees = m_flLightFOV; state.m_fVerticalFOVDegrees = m_flLightFOV; state.m_vecLightOrigin = vPos; BasisToQuaternion( vForward, vRight, vUp, state.m_quatOrientation ); state.m_fQuadraticAtten = 0.0; state.m_fLinearAtten = 100; state.m_fConstantAtten = 0.0f; state.m_Color[0] = m_LinearFloatLightColor.x; state.m_Color[1] = m_LinearFloatLightColor.y; state.m_Color[2] = m_LinearFloatLightColor.z; state.m_Color[3] = 0.0f; // fixme: need to make ambient work m_flAmbient; state.m_NearZ = m_flNearZ; state.m_FarZ = m_flFarZ; state.m_flShadowSlopeScaleDepthBias = mat_slopescaledepthbias_shadowmap.GetFloat(); state.m_flShadowDepthBias = mat_depthbias_shadowmap.GetFloat(); state.m_bEnableShadows = m_bEnableShadows; state.m_pSpotlightTexture = materials->FindTexture( m_SpotlightTextureName, TEXTURE_GROUP_OTHER, false ); state.m_nSpotlightTextureFrame = m_nSpotlightTextureFrame; state.m_nShadowQuality = m_nShadowQuality; // Allow entity to affect shadow quality if( m_LightHandle == CLIENTSHADOW_INVALID_HANDLE ) { m_LightHandle = g_pClientShadowMgr->CreateFlashlight( state ); } else { if ( m_hTargetEntity != NULL || bForceUpdate == true ) { g_pClientShadowMgr->UpdateFlashlightState( m_LightHandle, state ); } } if( m_bLightOnlyTarget ) { g_pClientShadowMgr->SetFlashlightTarget( m_LightHandle, m_hTargetEntity ); } else { g_pClientShadowMgr->SetFlashlightTarget( m_LightHandle, NULL ); } g_pClientShadowMgr->SetFlashlightLightWorld( m_LightHandle, m_bLightWorld ); //if ( bForceUpdate == false ) //{ g_pClientShadowMgr->UpdateProjectedTexture( m_LightHandle, true ); //} }
bool CParticleSystemQuery::IsPointInControllingObjectHitBox( CParticleCollection *pParticles, int nControlPointNumber, Vector vecPos, bool bBBoxOnly ) { bool bSuccess = false; #ifndef GAME_DLL EHANDLE *phMoveParent = reinterpret_cast<EHANDLE *> ( pParticles->m_ControlPoints[nControlPointNumber].m_pObject ); CBaseEntity *pMoveParent = NULL; if ( phMoveParent ) { pMoveParent = *( phMoveParent ); } if ( pMoveParent ) { s_BoneMutex.Lock(); C_BaseAnimating *pAnimating = pMoveParent->GetBaseAnimating(); bool bInBBox = false; Vector vecBBoxMin; Vector vecBBoxMax; Vector vecOrigin; vecBBoxMin = pMoveParent->CollisionProp()->OBBMins(); vecBBoxMax = pMoveParent->CollisionProp()->OBBMaxs(); matrix3x4_t matOrientation; matOrientation = pMoveParent->EntityToWorldTransform(); Vector vecLocalPos; VectorITransform( vecPos, matOrientation, vecLocalPos ); if ( IsPointInBox( vecLocalPos, vecBBoxMin, vecBBoxMax ) ) bInBBox = true; if ( bInBBox && bBBoxOnly ) bSuccess = true; else if ( pAnimating && bInBBox ) { matrix3x4_t *hitboxbones[MAXSTUDIOBONES]; if ( pAnimating->HitboxToWorldTransforms( hitboxbones ) ) { studiohdr_t *pStudioHdr = modelinfo->GetStudiomodel( pAnimating->GetModel() ); if ( pStudioHdr ) { mstudiohitboxset_t *set = pStudioHdr->pHitboxSet( pAnimating->GetHitboxSet() ); if ( set ) { // do a point in solid test Ray_t ray; trace_t tr; ray.Init( vecPos, vecPos ); enginetrace->ClipRayToEntity( ray, MASK_ALL, pMoveParent, &tr ); if ( tr.startsolid ) bSuccess = true; } } } } else if ( pMoveParent->IsBrushModel() && bInBBox ) { // do a point in solid test Ray_t ray; trace_t tr; ray.Init( vecPos, vecPos ); enginetrace->ClipRayToEntity( ray, MASK_ALL, pMoveParent, &tr ); if ( tr.startsolid ) bSuccess = true; } s_BoneMutex.Unlock(); } #endif return bSuccess; }
void C_EnvProjectedTexture::UpdateLight(void) { VPROF_BUDGET("C_EnvProjectedTexture::UpdateLight", "Projected Textures"); if (CurrentViewID() == VIEW_SHADOW_DEPTH_TEXTURE /*|| CurrentViewID() == VIEW_SUN_SHAFTS*/) return; bool bVisible = true; if (m_bAlwaysUpdate) { m_bForceUpdate = true; } float fHighFOV; if (m_flLightFOV > m_flLightHorFOV) fHighFOV = m_flLightFOV; else fHighFOV = m_flLightHorFOV; if (m_bState == false || !IsWithinFarZ(fHighFOV) || !IsBBoxVisible()) { // Spotlight's extents aren't in view ShutDownLightHandle(); return; } else { bVisible = true; } Vector vLinearFloatLightColor(m_LightColor.r, m_LightColor.g, m_LightColor.b); float flLinearFloatLightAlpha = m_LightColor.a; if (m_CurrentLinearFloatLightColor != vLinearFloatLightColor || m_flCurrentLinearFloatLightAlpha != flLinearFloatLightAlpha) { float flColorTransitionSpeed = gpGlobals->frametime * m_flColorTransitionTime * 255.0f; m_CurrentLinearFloatLightColor.x = Approach(vLinearFloatLightColor.x, m_CurrentLinearFloatLightColor.x, flColorTransitionSpeed); m_CurrentLinearFloatLightColor.y = Approach(vLinearFloatLightColor.y, m_CurrentLinearFloatLightColor.y, flColorTransitionSpeed); m_CurrentLinearFloatLightColor.z = Approach(vLinearFloatLightColor.z, m_CurrentLinearFloatLightColor.z, flColorTransitionSpeed); m_flCurrentLinearFloatLightAlpha = Approach(flLinearFloatLightAlpha, m_flCurrentLinearFloatLightAlpha, flColorTransitionSpeed); m_bForceUpdate = true; } if (m_LightHandle == CLIENTSHADOW_INVALID_HANDLE || m_hTargetEntity != NULL || GetRootMoveParent() != NULL || m_bForceUpdate) { Vector vForward, vRight, vUp, vPos = GetAbsOrigin(); FlashlightState_t state; if (m_hTargetEntity != NULL) { if (m_bCameraSpace) { const QAngle &angles = GetLocalAngles(); C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); if (pPlayer) { const QAngle playerAngles = pPlayer->GetAbsAngles(); Vector vPlayerForward, vPlayerRight, vPlayerUp; AngleVectors(playerAngles, &vPlayerForward, &vPlayerRight, &vPlayerUp); matrix3x4_t mRotMatrix; AngleMatrix(angles, mRotMatrix); VectorITransform(vPlayerForward, mRotMatrix, vForward); VectorITransform(vPlayerRight, mRotMatrix, vRight); VectorITransform(vPlayerUp, mRotMatrix, vUp); float dist = (m_hTargetEntity->GetAbsOrigin() - GetAbsOrigin()).Length(); vPos = m_hTargetEntity->GetAbsOrigin() - vForward*dist; VectorNormalize(vForward); VectorNormalize(vRight); VectorNormalize(vUp); } } else { Vector vecToTarget = m_hTargetEntity->GetAbsOrigin() - GetAbsOrigin(); QAngle vecAngles; VectorAngles(vecToTarget, vecAngles); AngleVectors(vecAngles, &vForward, &vRight, &vUp); } } else { AngleVectors(GetAbsAngles(), &vForward, &vRight, &vUp); } state.m_fHorizontalFOVDegrees = abs(m_flLightHorFOV); state.m_fVerticalFOVDegrees = abs(m_flLightFOV); state.m_vecLightOrigin = vPos; BasisToQuaternion(vForward, vRight, vUp, state.m_quatOrientation); state.m_NearZ = m_flNearZ; state.m_FarZ = m_flFarZ; // quickly check the proposed light's bbox against the view frustum to determine whether we // should bother to create it, if it doesn't exist, or cull it, if it does. // get the half-widths of the near and far planes, // based on the FOV which is in degrees. Remember that // on planet Valve, x is forward, y left, and z up. const float tanHalfAngle = tan(fHighFOV * (M_PI / 180.0f) * 0.5f); const float halfWidthNear = tanHalfAngle * m_flNearZ; const float halfWidthFar = tanHalfAngle * m_flFarZ; // now we can build coordinates in local space: the near rectangle is eg // (0, -halfWidthNear, -halfWidthNear), (0, halfWidthNear, -halfWidthNear), // (0, halfWidthNear, halfWidthNear), (0, -halfWidthNear, halfWidthNear) VectorAligned vNearRect[4] = { VectorAligned(m_flNearZ, -halfWidthNear, -halfWidthNear), VectorAligned(m_flNearZ, halfWidthNear, -halfWidthNear), VectorAligned(m_flNearZ, halfWidthNear, halfWidthNear), VectorAligned(m_flNearZ, -halfWidthNear, halfWidthNear) }; VectorAligned vFarRect[4] = { VectorAligned(m_flFarZ, -halfWidthFar, -halfWidthFar), VectorAligned(m_flFarZ, halfWidthFar, -halfWidthFar), VectorAligned(m_flFarZ, halfWidthFar, halfWidthFar), VectorAligned(m_flFarZ, -halfWidthFar, halfWidthFar) }; matrix3x4_t matOrientation(vForward, -vRight, vUp, vPos); enum { kNEAR = 0, kFAR = 1, }; VectorAligned vOutRects[2][4]; for (int i = 0; i < 4; ++i) { VectorTransform(vNearRect[i].Base(), matOrientation, vOutRects[0][i].Base()); } for (int i = 0; i < 4; ++i) { VectorTransform(vFarRect[i].Base(), matOrientation, vOutRects[1][i].Base()); } // now take the min and max extents for the bbox, and see if it is visible. Vector mins = **vOutRects; Vector maxs = **vOutRects; for (int i = 1; i < 8; ++i) { VectorMin(mins, *(*vOutRects + i), mins); VectorMax(maxs, *(*vOutRects + i), maxs); } #if 0 //for debugging the visibility frustum we just calculated NDebugOverlay::Triangle(vOutRects[0][0], vOutRects[0][1], vOutRects[0][2], 255, 0, 0, 100, true, 0.0f); //first tri NDebugOverlay::Triangle(vOutRects[0][2], vOutRects[0][1], vOutRects[0][0], 255, 0, 0, 100, true, 0.0f); //make it double sided NDebugOverlay::Triangle(vOutRects[0][2], vOutRects[0][3], vOutRects[0][0], 255, 0, 0, 100, true, 0.0f); //second tri NDebugOverlay::Triangle(vOutRects[0][0], vOutRects[0][3], vOutRects[0][2], 255, 0, 0, 100, true, 0.0f); //make it double sided NDebugOverlay::Triangle(vOutRects[1][0], vOutRects[1][1], vOutRects[1][2], 0, 0, 255, 100, true, 0.0f); //first tri NDebugOverlay::Triangle(vOutRects[1][2], vOutRects[1][1], vOutRects[1][0], 0, 0, 255, 100, true, 0.0f); //make it double sided NDebugOverlay::Triangle(vOutRects[1][2], vOutRects[1][3], vOutRects[1][0], 0, 0, 255, 100, true, 0.0f); //second tri NDebugOverlay::Triangle(vOutRects[1][0], vOutRects[1][3], vOutRects[1][2], 0, 0, 255, 100, true, 0.0f); //make it double sided NDebugOverlay::Box(vec3_origin, mins, maxs, 0, 255, 0, 100, 0.0f); #endif bool bVisible = IsBBoxVisible(mins, maxs); if (!bVisible) { // Spotlight's extents aren't in view if (m_LightHandle != CLIENTSHADOW_INVALID_HANDLE) { ShutDownLightHandle(); } return; } float flAlpha = m_flCurrentLinearFloatLightAlpha * (1.0f / 255.0f); state.m_fQuadraticAtten = m_flQuadratic; state.m_fLinearAtten = 100; if (m_bAtten) { state.m_fConstantAtten = 0.0f; } else { state.m_fConstantAtten = 1.0f; } state.m_Color[0] = (m_CurrentLinearFloatLightColor.x * (1.0f / 255.0f) * flAlpha) * m_fBrightness; state.m_Color[1] = (m_CurrentLinearFloatLightColor.y * (1.0f / 255.0f) * flAlpha) * m_fBrightness; state.m_Color[2] = (m_CurrentLinearFloatLightColor.z * (1.0f / 255.0f) * flAlpha) * m_fBrightness; state.m_Color[3] = m_flAmbient; state.m_flShadowSlopeScaleDepthBias = mat_slopescaledepthbias_shadowmap.GetFloat(); state.m_flShadowDepthBias = mat_depthbias_shadowmap.GetFloat(); if (m_bEnableShadows && r_flashlightdepthtexture.GetBool() && m_bClientWantsShadows) { state.m_bEnableShadows = true; } else { state.m_bEnableShadows = false; } state.m_pSpotlightTexture = m_SpotlightTexture; state.m_nSpotlightTextureFrame = m_nSpotlightTextureFrame; if (r_dynamicshadows_use_c17_improvements.GetBool()) { //state.m_flShadowFilterSize = m_flBlur; if (r_flashlightdepthres.GetInt() == 512) { state.m_flShadowFilterSize = 0.8f; } else if (r_flashlightdepthres.GetInt() == 1024) { state.m_flShadowFilterSize = 0.3f; } else if (r_flashlightdepthres.GetInt() == 2048) { state.m_flShadowFilterSize = 0.2f; } else if (r_flashlightdepthres.GetInt() == 4096) { state.m_flShadowFilterSize = 0.08f; } else { state.m_flShadowFilterSize = 1.0f; } state.m_flShadowAtten = m_flAtten; } else { state.m_flShadowFilterSize = 3.0f; state.m_flShadowAtten = 0.35f; } state.m_nShadowQuality = m_nShadowQuality; // Allow entity to affect shadow quality if (m_LightHandle == CLIENTSHADOW_INVALID_HANDLE) { // Hack: env projected textures don't work like normal flashlights; they're not assigned to a given splitscreen slot, // but the flashlight code requires this m_LightHandle = g_pClientShadowMgr->CreateFlashlight(state); if (m_LightHandle != CLIENTSHADOW_INVALID_HANDLE) { m_bForceUpdate = false; } } else { g_pClientShadowMgr->UpdateFlashlightState(m_LightHandle, state); m_bForceUpdate = false; } g_pClientShadowMgr->GetFrustumExtents(m_LightHandle, m_vecExtentsMin, m_vecExtentsMax); m_vecExtentsMin = m_vecExtentsMin - GetAbsOrigin(); m_vecExtentsMax = m_vecExtentsMax - GetAbsOrigin(); } if (m_bLightOnlyTarget) { g_pClientShadowMgr->SetFlashlightTarget(m_LightHandle, m_hTargetEntity); } else { g_pClientShadowMgr->SetFlashlightTarget(m_LightHandle, NULL); } g_pClientShadowMgr->SetFlashlightLightWorld(m_LightHandle, m_bLightWorld); if (!m_bForceUpdate) { g_pClientShadowMgr->UpdateProjectedTexture(m_LightHandle, true); } }
bool CStatueProp::CreateVPhysicsFromHitBoxes( CBaseAnimating *pInitBaseAnimating ) { if ( !pInitBaseAnimating ) return false; // Use the current animation sequence and cycle CopyAnimationDataFrom( pInitBaseAnimating ); // Copy over any render color color24 colorRender = pInitBaseAnimating->GetRenderColor(); SetRenderColor( colorRender.r, colorRender.g, colorRender.b ); SetRenderAlpha( pInitBaseAnimating->GetRenderAlpha() ); // Get hitbox data CStudioHdr *pStudioHdr = GetModelPtr(); if ( !pStudioHdr ) return false; mstudiohitboxset_t *set = pStudioHdr->pHitboxSet( m_nHitboxSet ); if ( !set ) return false; Vector position; QAngle angles; // Make enough pointers to convexes for each hitbox CPhysConvex **ppConvex = new (CPhysConvex*[ set->numhitboxes ]); float flTotalVolume = 0.0f; float flTotalSurfaceArea = 0.0f; for ( int i = 0; i < set->numhitboxes; i++ ) { // Get the hitbox info mstudiobbox_t *pbox = set->pHitbox( i ); GetBonePosition( pbox->bone, position, angles ); // Accumulate volume and area Vector flDimentions = pbox->bbmax - pbox->bbmin; flTotalVolume += flDimentions.x * flDimentions.y * flDimentions.z; flTotalSurfaceArea += 2.0f * ( flDimentions.x * flDimentions.y + flDimentions.x * flDimentions.z + flDimentions.y * flDimentions.z ); // Get angled min and max extents Vector vecMins, vecMaxs; VectorRotate( pbox->bbmin, angles, vecMins ); VectorRotate( pbox->bbmax, angles, vecMaxs ); // Get the corners in world space Vector vecMinCorner = position + vecMins; Vector vecMaxCorner = position + vecMaxs; // Get the normals of the hitbox in world space Vector vecForward, vecRight, vecUp; AngleVectors( angles, &vecForward, &vecRight, &vecUp ); vecRight = -vecRight; // Convert corners and normals to local space Vector vecCornerLocal[ 2 ]; Vector vecNormalLocal[ 3 ]; matrix3x4_t matToWorld = EntityToWorldTransform(); VectorITransform( vecMaxCorner, matToWorld, vecCornerLocal[ 0 ] ); VectorITransform( vecMinCorner, matToWorld, vecCornerLocal[ 1 ] ); VectorIRotate( vecForward, matToWorld, vecNormalLocal[ 0 ] ); VectorIRotate( vecRight, matToWorld, vecNormalLocal[ 1 ] ); VectorIRotate( vecUp, matToWorld, vecNormalLocal[ 2 ] ); // Create 6 planes from the local oriented hit box data float pPlanes[ 4 * 6 ]; for ( int iPlane = 0; iPlane < 6; ++iPlane ) { int iPlaneMod2 = iPlane % 2; int iPlaneDiv2 = iPlane / 2; bool bOdd = ( iPlaneMod2 == 1 ); // Plane Normal pPlanes[ iPlane * 4 + 0 ] = vecNormalLocal[ iPlaneDiv2 ].x * ( bOdd ? -1.0f : 1.0f ); pPlanes[ iPlane * 4 + 1 ] = vecNormalLocal[ iPlaneDiv2 ].y * ( bOdd ? -1.0f : 1.0f ); pPlanes[ iPlane * 4 + 2 ] = vecNormalLocal[ iPlaneDiv2 ].z * ( bOdd ? -1.0f : 1.0f ); // Plane D pPlanes[ iPlane * 4 + 3 ] = ( vecCornerLocal[ iPlaneMod2 ].x * vecNormalLocal[ iPlaneDiv2 ].x + vecCornerLocal[ iPlaneMod2 ].y * vecNormalLocal[ iPlaneDiv2 ].y + vecCornerLocal[ iPlaneMod2 ].z * vecNormalLocal[ iPlaneDiv2 ].z ) * ( bOdd ? -1.0f : 1.0f ); } // Create convex from the intersection of these planes ppConvex[ i ] = physcollision->ConvexFromPlanes( pPlanes, 6, 0.0f ); } // Make a single collide out of the group of convex boxes CPhysCollide *pPhysCollide = physcollision->ConvertConvexToCollide( ppConvex, set->numhitboxes ); delete[] ppConvex; // Create the physics object objectparams_t params = g_PhysDefaultObjectParams; params.pGameData = static_cast<void *>( this ); int nMaterialIndex = physprops->GetSurfaceIndex( "ice" ); // use ice material IPhysicsObject* p = physenv->CreatePolyObject( pPhysCollide, nMaterialIndex, GetAbsOrigin(), GetAbsAngles(), ¶ms ); Assert( p != NULL ); // Set velocity Vector vecInitialVelocity = pInitBaseAnimating->GetAbsVelocity(); p->SetVelocity( &vecInitialVelocity, NULL ); // Compute mass float flMass; float flDensity, flThickness; physprops->GetPhysicsProperties( nMaterialIndex, &flDensity, &flThickness, NULL, NULL ); // Make it more hollow flThickness = MIN ( 1.0f, flThickness + 0.5f ); if ( flThickness > 0.0f ) { flMass = flTotalSurfaceArea * flThickness * CUBIC_METERS_PER_CUBIC_INCH * flDensity; } else { // density is in kg/m^3, volume is in in^3 flMass = flTotalVolume * CUBIC_METERS_PER_CUBIC_INCH * flDensity; } // Mass is somewhere between the original and if it was all ice p->SetMass( flMass ); // Yes, gravity p->EnableGravity( true ); // Use this as our vphysics VPhysicsSetObject( p ); SetSolid( SOLID_VPHYSICS ); AddSolidFlags( FSOLID_CUSTOMRAYTEST | FSOLID_CUSTOMBOXTEST ); SetMoveType( MOVETYPE_VPHYSICS ); if ( pInitBaseAnimating != this ) { // Transfer children from the init base animating TransferChildren( pInitBaseAnimating, this ); CBaseEntity *pChild = FirstMoveChild(); while ( pChild ) { CEntityFreezing *pFreezing = dynamic_cast<CEntityFreezing*>( pChild ); if ( pFreezing ) { pFreezing->FinishFreezing(); } pChild = pChild->NextMovePeer(); } } return true; }
bool CStatueProp::CreateVPhysicsFromOBBs( CBaseAnimating *pInitBaseAnimating ) { // Make enough pointers to convexes for each hitbox CPhysConvex **ppConvex = new (CPhysConvex*[ m_pInitOBBs->Count() ]); float flTotalVolume = 0.0f; float flTotalSurfaceArea = 0.0f; for ( int i = 0; i < m_pInitOBBs->Count(); i++ ) { const outer_collision_obb_t *pOBB = &((*m_pInitOBBs)[ i ]); // Accumulate volume and area Vector flDimentions = pOBB->vecMaxs - pOBB->vecMins; flTotalVolume += flDimentions.x * flDimentions.y * flDimentions.z; flTotalSurfaceArea += 2.0f * ( flDimentions.x * flDimentions.y + flDimentions.x * flDimentions.z + flDimentions.y * flDimentions.z ); // Get angled min and max extents Vector vecMins, vecMaxs; VectorRotate( pOBB->vecMins, pOBB->angAngles, vecMins ); VectorRotate( pOBB->vecMaxs, pOBB->angAngles, vecMaxs ); // Get the corners in world space Vector vecMinCorner = pOBB->vecPos + vecMins; Vector vecMaxCorner = pOBB->vecPos + vecMaxs; // Get the normals of the hitbox in world space Vector vecForward, vecRight, vecUp; AngleVectors( pOBB->angAngles, &vecForward, &vecRight, &vecUp ); vecRight = -vecRight; // Convert corners and normals to local space Vector vecCornerLocal[ 2 ]; Vector vecNormalLocal[ 3 ]; matrix3x4_t matToWorld = EntityToWorldTransform(); VectorITransform( vecMaxCorner, matToWorld, vecCornerLocal[ 0 ] ); VectorITransform( vecMinCorner, matToWorld, vecCornerLocal[ 1 ] ); VectorIRotate( vecForward, matToWorld, vecNormalLocal[ 0 ] ); VectorIRotate( vecRight, matToWorld, vecNormalLocal[ 1 ] ); VectorIRotate( vecUp, matToWorld, vecNormalLocal[ 2 ] ); // Create 6 planes from the local oriented hit box data float pPlanes[ 4 * 6 ]; for ( int iPlane = 0; iPlane < 6; ++iPlane ) { int iPlaneMod2 = iPlane % 2; int iPlaneDiv2 = iPlane / 2; bool bOdd = ( iPlaneMod2 == 1 ); // Plane Normal pPlanes[ iPlane * 4 + 0 ] = vecNormalLocal[ iPlaneDiv2 ].x * ( bOdd ? -1.0f : 1.0f ); pPlanes[ iPlane * 4 + 1 ] = vecNormalLocal[ iPlaneDiv2 ].y * ( bOdd ? -1.0f : 1.0f ); pPlanes[ iPlane * 4 + 2 ] = vecNormalLocal[ iPlaneDiv2 ].z * ( bOdd ? -1.0f : 1.0f ); // Plane D pPlanes[ iPlane * 4 + 3 ] = ( vecCornerLocal[ iPlaneMod2 ].x * vecNormalLocal[ iPlaneDiv2 ].x + vecCornerLocal[ iPlaneMod2 ].y * vecNormalLocal[ iPlaneDiv2 ].y + vecCornerLocal[ iPlaneMod2 ].z * vecNormalLocal[ iPlaneDiv2 ].z ) * ( bOdd ? -1.0f : 1.0f ); } // Create convex from the intersection of these planes ppConvex[ i ] = physcollision->ConvexFromPlanes( pPlanes, 6, 0.0f ); } // Make a single collide out of the group of convex boxes CPhysCollide *pPhysCollide = physcollision->ConvertConvexToCollide( ppConvex, m_pInitOBBs->Count() ); delete[] ppConvex; // Create the physics object objectparams_t params = g_PhysDefaultObjectParams; params.pGameData = static_cast<void *>( this ); int nMaterialIndex = physprops->GetSurfaceIndex( "ice" ); // use ice material IPhysicsObject* p = physenv->CreatePolyObject( pPhysCollide, nMaterialIndex, GetAbsOrigin(), GetAbsAngles(), ¶ms ); Assert( p != NULL ); // Set velocity Vector vecInitialVelocity = pInitBaseAnimating->GetAbsVelocity(); p->SetVelocity( &vecInitialVelocity, NULL ); // Compute mass float flMass; float flDensity, flThickness; physprops->GetPhysicsProperties( nMaterialIndex, &flDensity, &flThickness, NULL, NULL ); // Make it more hollow flThickness = MIN ( 1.0f, flThickness + 0.5f ); if ( flThickness > 0.0f ) { flMass = flTotalSurfaceArea * flThickness * CUBIC_METERS_PER_CUBIC_INCH * flDensity; } else { // density is in kg/m^3, volume is in in^3 flMass = flTotalVolume * CUBIC_METERS_PER_CUBIC_INCH * flDensity; } // Mass is somewhere between the original and if it was all ice p->SetMass( flMass ); // Yes, gravity p->EnableGravity( true ); // Use this as our vphysics VPhysicsSetObject( p ); SetSolid( SOLID_VPHYSICS ); AddSolidFlags( FSOLID_CUSTOMRAYTEST | FSOLID_CUSTOMBOXTEST ); SetMoveType( MOVETYPE_VPHYSICS ); m_pInitOBBs = NULL; return true; }
void CGrabController::AttachEntity( CBasePlayer *pPlayer, CBaseEntity *pEntity, IPhysicsObject *pPhys, bool bIsMegaPhysCannon, const Vector &vGrabPosition, bool bUseGrabPosition ) { // play the impact sound of the object hitting the player // used as feedback to let the player know he picked up the object int hitMaterial = pPhys->GetMaterialIndex(); int playerMaterial = pPlayer->VPhysicsGetObject() ? pPlayer->VPhysicsGetObject()->GetMaterialIndex() : hitMaterial; PhysicsImpactSound( pPlayer, pPhys, CHAN_STATIC, hitMaterial, playerMaterial, 1.0, 64 ); Vector position; QAngle angles; pPhys->GetPosition( &position, &angles ); // If it has a preferred orientation, use that instead. Pickup_GetPreferredCarryAngles( pEntity, pPlayer, pPlayer->EntityToWorldTransform(), angles ); // ComputeMaxSpeed( pEntity, pPhys ); // If we haven't been killed by a grab, we allow the gun to grab the nearest part of a ragdoll if ( bUseGrabPosition ) { IPhysicsObject *pChild = GetRagdollChildAtPosition( pEntity, vGrabPosition ); if ( pChild ) { pPhys = pChild; } } // Carried entities can never block LOS m_bCarriedEntityBlocksLOS = pEntity->BlocksLOS(); pEntity->SetBlocksLOS( false ); m_controller = physenv->CreateMotionController( this ); m_controller->AttachObject( pPhys, true ); // Don't do this, it's causing trouble with constraint solvers. //m_controller->SetPriority( IPhysicsMotionController::HIGH_PRIORITY ); pPhys->Wake(); PhysSetGameFlags( pPhys, FVPHYSICS_PLAYER_HELD ); SetTargetPosition( position, angles ); m_attachedEntity = pEntity; IPhysicsObject *pList[VPHYSICS_MAX_OBJECT_LIST_COUNT]; int count = pEntity->VPhysicsGetObjectList( pList, ARRAYSIZE(pList) ); m_flLoadWeight = 0; float damping = 10; float flFactor = count / 7.5f; if ( flFactor < 1.0f ) { flFactor = 1.0f; } for ( int i = 0; i < count; i++ ) { float mass = pList[i]->GetMass(); pList[i]->GetDamping( NULL, &m_savedRotDamping[i] ); m_flLoadWeight += mass; m_savedMass[i] = mass; // reduce the mass to prevent the player from adding crazy amounts of energy to the system pList[i]->SetMass( REDUCED_CARRY_MASS / flFactor ); pList[i]->SetDamping( NULL, &damping ); } // Give extra mass to the phys object we're actually picking up pPhys->SetMass( REDUCED_CARRY_MASS ); pPhys->EnableDrag( false ); m_errorTime = bIsMegaPhysCannon ? -1.5f : -1.0f; // 1 seconds until error starts accumulating m_error = 0; m_contactAmount = 0; m_attachedAnglesPlayerSpace = TransformAnglesToPlayerSpace( angles, pPlayer ); if ( m_angleAlignment != 0 ) { m_attachedAnglesPlayerSpace = AlignAngles( m_attachedAnglesPlayerSpace, m_angleAlignment ); } // Ragdolls don't offset this way if ( dynamic_cast<CRagdollProp*>(pEntity) ) { m_attachedPositionObjectSpace.Init(); } else { VectorITransform( pEntity->WorldSpaceCenter(), pEntity->EntityToWorldTransform(), m_attachedPositionObjectSpace ); } // If it's a prop, see if it has desired carry angles CPhysicsProp *pProp = dynamic_cast<CPhysicsProp *>(pEntity); if ( pProp ) { m_bHasPreferredCarryAngles = pProp->GetPropDataAngles( "preferred_carryangles", m_vecPreferredCarryAngles ); m_flDistanceOffset = pProp->GetCarryDistanceOffset(); } else { m_bHasPreferredCarryAngles = false; m_flDistanceOffset = 0; } m_bAllowObjectOverhead = IsObjectAllowedOverhead( pEntity ); }
void CFourWheelVehiclePhysics::CalcWheelData( vehicleparams_t &vehicle ) { Vector left, right; QAngle dummy; SetPoseParameter( m_poseParameters[VEH_FL_WHEEL_HEIGHT], 0 ); SetPoseParameter( m_poseParameters[VEH_FR_WHEEL_HEIGHT], 0 ); SetPoseParameter( m_poseParameters[VEH_RL_WHEEL_HEIGHT], 0 ); SetPoseParameter( m_poseParameters[VEH_RR_WHEEL_HEIGHT], 0 ); m_pOuter->InvalidateBoneCache(); if ( GetAttachment( "wheel_fl", left, dummy ) && GetAttachment( "wheel_fr", right, dummy ) ) { VectorITransform( left, m_pOuter->EntityToWorldTransform(), left ); VectorITransform( right, m_pOuter->EntityToWorldTransform(), right ); Vector center = (left + right) * 0.5; vehicle.axles[0].offset = center; vehicle.axles[0].wheelOffset = right - center; // Cache the base height of the wheels in body space m_wheelBaseHeight[0] = left.z; m_wheelBaseHeight[1] = right.z; } if ( GetAttachment( "wheel_rl", left, dummy ) && GetAttachment( "wheel_rr", right, dummy ) ) { VectorITransform( left, m_pOuter->EntityToWorldTransform(), left ); VectorITransform( right, m_pOuter->EntityToWorldTransform(), right ); Vector center = (left + right) * 0.5; vehicle.axles[1].offset = center; vehicle.axles[1].wheelOffset = right - center; // Cache the base height of the wheels in body space m_wheelBaseHeight[2] = left.z; m_wheelBaseHeight[3] = right.z; } SetPoseParameter( m_poseParameters[VEH_FL_WHEEL_HEIGHT], 1 ); SetPoseParameter( m_poseParameters[VEH_FR_WHEEL_HEIGHT], 1 ); SetPoseParameter( m_poseParameters[VEH_RL_WHEEL_HEIGHT], 1 ); SetPoseParameter( m_poseParameters[VEH_RR_WHEEL_HEIGHT], 1 ); m_pOuter->InvalidateBoneCache(); if ( GetAttachment( "wheel_fl", left, dummy ) && GetAttachment( "wheel_fr", right, dummy ) ) { VectorITransform( left, m_pOuter->EntityToWorldTransform(), left ); VectorITransform( right, m_pOuter->EntityToWorldTransform(), right ); // Cache the height range of the wheels in body space m_wheelTotalHeight[0] = m_wheelBaseHeight[0] - left.z; m_wheelTotalHeight[1] = m_wheelBaseHeight[1] - right.z; vehicle.axles[0].wheels.springAdditionalLength = m_wheelTotalHeight[0]; } if ( GetAttachment( "wheel_rl", left, dummy ) && GetAttachment( "wheel_rr", right, dummy ) ) { VectorITransform( left, m_pOuter->EntityToWorldTransform(), left ); VectorITransform( right, m_pOuter->EntityToWorldTransform(), right ); // Cache the height range of the wheels in body space m_wheelTotalHeight[2] = m_wheelBaseHeight[0] - left.z; m_wheelTotalHeight[3] = m_wheelBaseHeight[1] - right.z; vehicle.axles[1].wheels.springAdditionalLength = m_wheelTotalHeight[2]; } SetPoseParameter( m_poseParameters[VEH_FL_WHEEL_HEIGHT], 0 ); SetPoseParameter( m_poseParameters[VEH_FR_WHEEL_HEIGHT], 0 ); SetPoseParameter( m_poseParameters[VEH_RL_WHEEL_HEIGHT], 0 ); SetPoseParameter( m_poseParameters[VEH_RR_WHEEL_HEIGHT], 0 ); m_pOuter->InvalidateBoneCache(); // Get raytrace offsets if they exist. if ( GetAttachment( "raytrace_fl", left, dummy ) && GetAttachment( "raytrace_fr", right, dummy ) ) { VectorITransform( left, m_pOuter->EntityToWorldTransform(), left ); VectorITransform( right, m_pOuter->EntityToWorldTransform(), right ); Vector center = ( left + right ) * 0.5; vehicle.axles[0].raytraceCenterOffset = center; vehicle.axles[0].raytraceOffset = right - center; } if ( GetAttachment( "raytrace_rl", left, dummy ) && GetAttachment( "raytrace_rr", right, dummy ) ) { VectorITransform( left, m_pOuter->EntityToWorldTransform(), left ); VectorITransform( right, m_pOuter->EntityToWorldTransform(), right ); Vector center = ( left + right ) * 0.5; vehicle.axles[1].raytraceCenterOffset = center; vehicle.axles[1].raytraceOffset = right - center; } }