void C_NPC_Hydra::CalcBoneChain( Vector pos[], const Vector chain[] ) { int i, j; // Find the dist chain link that's not zero length i = CHAIN_LINKS-1; while (i > 0) { if ((chain[i] - chain[i-1]).LengthSqr() > 0.0) { break; } i--; } // initialize the last bone to the last bone j = m_numHydraBones - 1; // clamp length float totalLength = 0; for (int k = i; k > 0; k--) { // debugoverlay->AddLineOverlay( chain[k], chain[k-1], 255, 255, 255, false, 0 ); totalLength += (chain[k] - chain[k-1]).Length(); } totalLength = clamp( totalLength, 1.0, m_maxPossibleLength ); float scale = m_flRelaxedLength / totalLength; // starting from the head, fit the hydra skeleton onto the chain spline float dist = -16; while (j >= 0 && i > 0) { // debugoverlay->AddLineOverlay( chain[i], chain[i-1], 255, 255, 255, false, 0 ); float dt = (chain[i] - chain[i-1]).Length() * scale; float dx = dt; while (j >= 0 && dist + dt >= m_boneLength[j]) { float s = (dx - (dt - (m_boneLength[j] - dist))) / dx; if (s < 0 || s > 1.) s = 0; // pos[j] = chain[i] * (1 - s) + chain[i-1] * s; Catmull_Rom_Spline( chain[(i<CHAIN_LINKS-1)?i+1:CHAIN_LINKS-1], chain[i], chain[(i>0)?i-1:0], chain[(i>1)?i-2:0], s, pos[j] ); // debugoverlay->AddLineOverlay( pos[j], chain[i], 0, 255, 0, false, 0 ); // debugoverlay->AddLineOverlay( pos[j], chain[i-1], 0, 255, 0, false, 0 ); dt = dt - (m_boneLength[j] - dist); j--; dist = 0; } dist += dt; i--; } while (j >= 0) { pos[j] = chain[0]; j--; } }
void CPositionInterpolator_CatmullRom::InterpolatePosition( float time, Vector &vOut ) { Catmull_Rom_Spline( g_KeyFramePtr[-1].vPos, g_KeyFramePtr[0].vPos, g_KeyFramePtr[1].vPos, g_KeyFramePtr[2].vPos, time, vOut ); }
void Interpolator_CurveInterpolate_NonNormalized( int interpolationType, const Vector &vPre, const Vector &vStart, const Vector &vEnd, const Vector &vNext, float f, Vector &vOut ) { vOut.Init(); switch ( interpolationType ) { default: Warning( "Unknown interpolation type %d\n", (int)interpolationType ); // break; // Fall through and use catmull_rom as default case INTERPOLATE_CATMULL_ROM_NORMALIZEX: case INTERPOLATE_DEFAULT: case INTERPOLATE_CATMULL_ROM: case INTERPOLATE_CATMULL_ROM_NORMALIZE: case INTERPOLATE_CATMULL_ROM_TANGENT: Catmull_Rom_Spline( vPre, vStart, vEnd, vNext, f, vOut ); break; case INTERPOLATE_EASE_IN: { f = sin( M_PI * f * 0.5f ); // Fixme, since this ignores vPre and vNext we could omit computing them aove VectorLerp( vStart, vEnd, f, vOut ); } break; case INTERPOLATE_EASE_OUT: { f = 1.0f - sin( M_PI * f * 0.5f + 0.5f * M_PI ); // Fixme, since this ignores vPre and vNext we could omit computing them aove VectorLerp( vStart, vEnd, f, vOut ); } break; case INTERPOLATE_EASE_INOUT: { f = SimpleSpline( f ); // Fixme, since this ignores vPre and vNext we could omit computing them aove VectorLerp( vStart, vEnd, f, vOut ); } break; case INTERPOLATE_LINEAR_INTERP: // Fixme, since this ignores vPre and vNext we could omit computing them aove VectorLerp( vStart, vEnd, f, vOut ); break; case INTERPOLATE_KOCHANEK_BARTELS: case INTERPOLATE_KOCHANEK_BARTELS_EARLY: case INTERPOLATE_KOCHANEK_BARTELS_LATE: { float t, b, c; Interpolator_GetKochanekBartelsParams( interpolationType, t, b, c ); Kochanek_Bartels_Spline ( t, b, c, vPre, vStart, vEnd, vNext, f, vOut ); } break; case INTERPOLATE_SIMPLE_CUBIC: Cubic_Spline( vPre, vStart, vEnd, vNext, f, vOut ); break; case INTERPOLATE_BSPLINE: BSpline( vPre, vStart, vEnd, vNext, f, vOut ); break; case INTERPOLATE_EXPONENTIAL_DECAY: { float dt = vEnd.x - vStart.x; if ( dt > 0.0f ) { float val = 1.0f - ExponentialDecay( 0.001, dt, f * dt ); vOut.y = vStart.y + val * ( vEnd.y - vStart.y ); } else { vOut.y = vStart.y; } } break; case INTERPOLATE_HOLD: { vOut.y = vStart.y; } break; } }
void CViewAngleAnimation::ClientThink() { if ( IsFinished() ) return; float flCurrentTime = gpGlobals->curtime - m_flAnimStartTime; if ( flCurrentTime < 0 ) flCurrentTime = 0.001; // find two nearest points int i, c; c = m_KeyFrames.Count(); float flTime = 0; for ( i=0;i<c;i++ ) { if ( flTime + m_KeyFrames[i]->m_flTime > flCurrentTime ) { break; } flTime += m_KeyFrames[i]->m_flTime; } Assert( i > 0 ); if ( i >= c ) { if ( i > 0 ) { // animation complete, set to end point SetAngles( m_KeyFrames[i-1]->m_vecAngles ); } if ( m_pAnimCompleteCallback ) { m_pAnimCompleteCallback(); } m_bFinished = true; return; } if ( m_KeyFrames[i]->m_iFlags != m_iFlags ) { if ( ( m_KeyFrames[i]->m_iFlags & VIEWANIM_RELATIVE ) && !( m_iFlags & VIEWANIM_RELATIVE ) ) { // new relative position is current angles engine->GetViewAngles( m_vecBaseAngles ); } // copy the rest over m_iFlags = m_KeyFrames[i]->m_iFlags; } // previous frame is m_KeyFrames[i-1]; // next frame is m_KeyFrames[i]; float flFraction = ( flCurrentTime - flTime ) / ( m_KeyFrames[i]->m_flTime ); Vector v0, v1, v2, v3; if ( i-2 <= 0 ) { QAngleToVector( m_KeyFrames[i-1]->m_vecAngles, v0 ); } else { QAngleToVector( m_KeyFrames[i-2]->m_vecAngles, v0 ); } QAngleToVector( m_KeyFrames[i-1]->m_vecAngles, v1 ); QAngleToVector( m_KeyFrames[i]->m_vecAngles, v2 ); if ( i+1 >= c ) { QAngleToVector( m_KeyFrames[i]->m_vecAngles, v3 ); } else { QAngleToVector( m_KeyFrames[i+1]->m_vecAngles, v3 ); } Vector out; Catmull_Rom_Spline( v0, v1, v2, v3, flFraction, out ); QAngle vecCalculatedAngles; QAngleToVector( out, vecCalculatedAngles ); SetAngles( vecCalculatedAngles ); }
//----------------------------------------------------------------------------- // Purpose: // Input : time - // type - // Output : float //----------------------------------------------------------------------------- float CSentence::GetIntensity( float time, float endtime ) { float zeroValue = 0.5f; int c = GetNumSamples(); if ( c <= 0 ) { return zeroValue; } int i; for ( i = -1 ; i < c; i++ ) { CEmphasisSample *s = GetBoundedSample( i, endtime ); CEmphasisSample *n = GetBoundedSample( i + 1, endtime ); if ( !s || !n ) continue; if ( time >= s->time && time <= n->time ) { break; } } int prev = i - 1; int start = i; int end = i + 1; int next = i + 2; prev = max( -1, prev ); start = max( -1, start ); end = min( end, GetNumSamples() ); next = min( next, GetNumSamples() ); CEmphasisSample *esPre = GetBoundedSample( prev, endtime ); CEmphasisSample *esStart = GetBoundedSample( start, endtime ); CEmphasisSample *esEnd = GetBoundedSample( end, endtime ); CEmphasisSample *esNext = GetBoundedSample( next, endtime ); float dt = esEnd->time - esStart->time; dt = clamp( dt, 0.01f, 1.0f ); Vector vPre( esPre->time, esPre->value, 0 ); Vector vStart( esStart->time, esStart->value, 0 ); Vector vEnd( esEnd->time, esEnd->value, 0 ); Vector vNext( esNext->time, esNext->value, 0 ); float f2 = ( time - esStart->time ) / ( dt ); f2 = clamp( f2, 0.0f, 1.0f ); Vector vOut; Catmull_Rom_Spline( vPre, vStart, vEnd, vNext, f2, vOut ); float retval = clamp( vOut.y, 0.0f, 1.0f ); return retval; }
void C_Camera::CalcTVCamView(Vector& eyeOrigin, QAngle& eyeAngles, float& fov) { if (!GetMatchBall()) return; C_BaseEntity *pTarget; bool atMinGoalPos; Vector targetPos; int tvcamMode = GetTVCamMode(); if (GetReplayManager() && GetReplayManager()->IsReplaying()) { pTarget = GetReplayBall(); if (!pTarget) return; atMinGoalPos = GetReplayManager()->m_bAtMinGoalPos; targetPos = pTarget->GetLocalOrigin(); } else { if (GetMatchBall() && GetMatchBall()->m_eBallState == BALL_STATE_GOAL) { pTarget = GetMatchBall()->m_pLastActivePlayer; if (!pTarget) pTarget = GetMatchBall(); atMinGoalPos = pTarget->GetLocalOrigin().y < SDKGameRules()->m_vKickOff.GetY(); targetPos = pTarget->GetLocalOrigin(); } else { pTarget = CBasePlayer::GetLocalPlayer()->GetObserverTarget(); if (!pTarget) pTarget = GetMatchBall(); atMinGoalPos = pTarget->GetLocalOrigin().y < SDKGameRules()->m_vKickOff.GetY(); targetPos = pTarget->GetLocalOrigin(); // Move the camera towards the defending team's goal if (GetMatchBall()->m_nLastActiveTeam != TEAM_NONE) { if (m_nLastPossessingTeam == TEAM_NONE) { m_nLastPossessingTeam = GetMatchBall()->m_nLastActiveTeam; m_flLastPossessionChange = gpGlobals->curtime; m_flPossCoeff = 0; m_flOldPossCoeff = 0; } else { if (GetMatchBall()->m_nLastActiveTeam != m_nLastPossessingTeam) { m_nLastPossessingTeam = GetMatchBall()->m_nLastActiveTeam; m_flLastPossessionChange = gpGlobals->curtime; m_flOldPossCoeff = m_flPossCoeff; } float timeFrac = min(1.0f, (gpGlobals->curtime - m_flLastPossessionChange) / mp_tvcam_offset_forward_time.GetFloat()); float frac = pow(timeFrac, 2) * (3 - 2 * timeFrac); m_flPossCoeff = Lerp(frac, m_flOldPossCoeff, (float)GetGlobalTeam(GetMatchBall()->m_nLastActiveTeam)->m_nForward); } if (tvcamMode == TVCAM_MODE_SIDELINE) { targetPos.y += m_flPossCoeff * mp_tvcam_offset_forward.GetInt(); } } } } if (tvcamMode != TVCAM_MODE_CELEBRATION) { // Make sure the camera doesn't move too far away from the field borders targetPos.x = clamp(targetPos.x, SDKGameRules()->m_vFieldMin.GetX() + mp_tvcam_border_south.GetInt(), SDKGameRules()->m_vFieldMax.GetX() - mp_tvcam_border_north.GetInt()); targetPos.y = clamp(targetPos.y, SDKGameRules()->m_vFieldMin.GetY() + mp_tvcam_border_west.GetInt(), SDKGameRules()->m_vFieldMax.GetY() - mp_tvcam_border_east.GetInt()); targetPos.z = SDKGameRules()->m_vKickOff.GetZ(); } if (m_vOldTargetPos == vec3_invalid) m_vOldTargetPos = targetPos; else { float speedCoeff = tvcamMode == TVCAM_MODE_CELEBRATION ? mp_tvcam_speed_coeff_fast.GetFloat() : mp_tvcam_speed_coeff.GetFloat(); float speedExp = tvcamMode == TVCAM_MODE_CELEBRATION ? mp_tvcam_speed_exponent_fast.GetFloat() : mp_tvcam_speed_exponent.GetFloat(); Vector changeDir = targetPos - m_vOldTargetPos; float changeDist = changeDir.Length(); changeDir.NormalizeInPlace(); targetPos = m_vOldTargetPos + changeDir * min(changeDist, pow(changeDist * speedCoeff, speedExp) * gpGlobals->frametime); } switch (GetTVCamMode()) { case TVCAM_MODE_SIDELINE: { if (SDKGameRules() && SDKGameRules()->IsIntermissionState() && GetReplayManager() && !GetReplayManager()->IsReplaying()) { //float xLength = SDKGameRules()->m_vFieldMax.GetX() - SDKGameRules()->m_vFieldMin.GetX(); //float yLength = SDKGameRules()->m_vFieldMax.GetY() - SDKGameRules()->m_vFieldMin.GetY(); float zPos = 450; Vector points[4]; points[0] = Vector(SDKGameRules()->m_vFieldMin.GetX(), SDKGameRules()->m_vFieldMin.GetY(), SDKGameRules()->m_vKickOff.GetZ() + zPos); points[1] = Vector(SDKGameRules()->m_vFieldMin.GetX(), SDKGameRules()->m_vFieldMax.GetY(), SDKGameRules()->m_vKickOff.GetZ() + zPos); points[2] = Vector(SDKGameRules()->m_vFieldMax.GetX(), SDKGameRules()->m_vFieldMax.GetY(), SDKGameRules()->m_vKickOff.GetZ() + zPos); points[3] = Vector(SDKGameRules()->m_vFieldMax.GetX(), SDKGameRules()->m_vFieldMin.GetY(), SDKGameRules()->m_vKickOff.GetZ() + zPos); float totalLength = (points[1] - points[0]).Length() + (points[2] - points[1]).Length() + (points[3] - points[2]).Length() + (points[0] - points[3]).Length(); Vector newPoints[4]; const float maxDuration = 180.0f; float timePassed = fmodf(gpGlobals->curtime, maxDuration); float lengthSum = 0; int offset = 0; float length = 0; do { for (int i = 0; i < 4; i++) newPoints[i] = points[(i + offset) % 4]; length = (newPoints[2] - newPoints[1]).Length(); lengthSum += length; offset += 1; } while (timePassed > (lengthSum / totalLength * maxDuration)); float maxStepTime = length / totalLength * maxDuration; float frac = 1 - ((lengthSum / totalLength * maxDuration) - timePassed) / maxStepTime; Vector output; Catmull_Rom_Spline(newPoints[0], newPoints[1], newPoints[2], newPoints[3], frac, output); /* float targetDist = (newPoints[2] - newPoints[1]).Length() * frac; float epsilon = 10.0f; float oldDiff = 0; float diff = 0; float change = 0.001f; bool add = true; do { frac = clamp(frac += (add ? change : -change), 0.0f, 1.0f); Catmull_Rom_Spline(newPoints[0], newPoints[1], newPoints[2], newPoints[3], frac, output); oldDiff = diff; diff = abs((output - newPoints[1]).Length() - targetDist); if (diff >= oldDiff) add = !add; } while (diff > epsilon);*/ eyeOrigin = output; VectorAngles(SDKGameRules()->m_vKickOff - output, eyeAngles); } /*else if (SDKGameRules() && !SDKGameRules()->IsIntermissionState() && gpGlobals->curtime <= SDKGameRules()->m_flStateEnterTime + 4) { Vector points[4]; float zPosStart = 450; float zPosEnd = 50; points[0] = Vector(SDKGameRules()->m_vFieldMin.GetX(), SDKGameRules()->m_vKickOff.GetY() + 10000, SDKGameRules()->m_vKickOff.GetZ() + zPosStart); points[1] = Vector(SDKGameRules()->m_vFieldMin.GetX(), SDKGameRules()->m_vKickOff.GetY(), SDKGameRules()->m_vKickOff.GetZ() + zPosStart); points[2] = Vector(SDKGameRules()->m_vKickOff.GetX(), SDKGameRules()->m_vKickOff.GetY() - 300, SDKGameRules()->m_vKickOff.GetZ() + zPosEnd); points[3] = Vector(SDKGameRules()->m_vKickOff.GetX(), SDKGameRules()->m_vKickOff.GetY() + 10000, SDKGameRules()->m_vKickOff.GetZ() + zPosEnd); float frac = min(1.0f, (gpGlobals->curtime - SDKGameRules()->m_flStateEnterTime) / 3.0f); Vector output; Catmull_Rom_Spline(points[0], points[1], points[2], points[3], frac, output); eyeOrigin = output; VectorAngles(Vector(SDKGameRules()->m_vKickOff.GetX(), SDKGameRules()->m_vKickOff.GetY(), SDKGameRules()->m_vKickOff.GetZ() + 100) - output, eyeAngles); }*/ else { Vector newPos = Vector(targetPos.x - mp_tvcam_sideline_offset_north.GetInt(), targetPos.y, targetPos.z + mp_tvcam_sideline_offset_height.GetInt()); Vector offsetTargetPos = Vector(targetPos.x - mp_tvcam_offset_north.GetInt(), targetPos.y, targetPos.z); Vector newDir = offsetTargetPos - newPos; newDir.NormalizeInPlace(); eyeOrigin = newPos; VectorAngles(newDir, eyeAngles); } } break; case TVCAM_MODE_FIXED_SIDELINE: { Vector newPos = Vector(SDKGameRules()->m_vFieldMin.GetX() - 500, SDKGameRules()->m_vKickOff.GetY(), SDKGameRules()->m_vKickOff.GetZ() + 1000); Vector offsetTargetPos = Vector(targetPos.x - 500, targetPos.y, targetPos.z); Vector newDir = offsetTargetPos - newPos; float dist = newDir.Length(); newDir.NormalizeInPlace(); newPos = offsetTargetPos - min(750, dist) * newDir; eyeOrigin = newPos; VectorAngles(newDir, eyeAngles); } break; case TVCAM_MODE_BEHIND_GOAL: { float yPos = atMinGoalPos ? SDKGameRules()->m_vFieldMin.GetY() : SDKGameRules()->m_vFieldMax.GetY(); Vector goalCenter = Vector((SDKGameRules()->m_vFieldMin.GetX() + SDKGameRules()->m_vFieldMax.GetX()) / 2.0f, yPos, SDKGameRules()->m_vKickOff.GetZ()); Vector newPos = goalCenter + Vector(0, 300 * (atMinGoalPos ? -1 : 1), 300); Vector newDir = targetPos - newPos; newDir.NormalizeInPlace(); eyeOrigin = newPos; VectorAngles(newDir, eyeAngles); } break; case TVCAM_MODE_TOPDOWN: { eyeOrigin = Vector(targetPos.x, targetPos.y, SDKGameRules()->m_vKickOff.GetZ() + 1000); eyeAngles = QAngle(89, 0, 0); } break; case TVCAM_MODE_FLY_FOLLOW: { Vector newPos = Vector(targetPos.x, targetPos.y + (atMinGoalPos ? 1 : -1) * 500, SDKGameRules()->m_vKickOff.GetZ() + 225); Vector newDir = targetPos - newPos; newDir.NormalizeInPlace(); eyeOrigin = newPos; VectorAngles(newDir, eyeAngles); } break; case TVCAM_MODE_GOAL_LINE: { Vector center = Vector(SDKGameRules()->m_vKickOff.GetX(), (atMinGoalPos ? SDKGameRules()->m_vFieldMin.GetY() + 5 : SDKGameRules()->m_vFieldMax.GetY() - 5), SDKGameRules()->m_vKickOff.GetZ()); Vector newPos = center; newPos.x -= 350; newPos.z += 200; QAngle newAng; VectorAngles(center - newPos, newAng); eyeOrigin = newPos; eyeAngles = newAng; } break; case TVCAM_MODE_CELEBRATION: { Vector newPos = Vector( targetPos.x < SDKGameRules()->m_vKickOff.GetX() ? SDKGameRules()->m_vFieldMin.GetX() - 500 : SDKGameRules()->m_vFieldMax.GetX() + 500, targetPos.y < SDKGameRules()->m_vKickOff.GetY() ? SDKGameRules()->m_vFieldMin.GetY() - 500 : SDKGameRules()->m_vFieldMax.GetY() + 500, SDKGameRules()->m_vKickOff.GetZ() + 1000); Vector newDir = targetPos - newPos; float dist = newDir.Length(); newDir.NormalizeInPlace(); newPos = targetPos - min(300, dist) * newDir; eyeOrigin = newPos; VectorAngles(newDir, eyeAngles); } break; } m_vOldTargetPos = targetPos; fov = C_SDKPlayer::GetLocalSDKPlayer()->GetFOV(); }