欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

线性插值、Sin插值、震荡插值

程序员文章站 2024-03-24 11:50:34
...

线性插值:根据开始时间、结束时间和当前时间,线性的计算开始值、结束值之间的一个数

/*
*fStart:开始值
*fEnd:结束值
*dwStart:开始时间
*dwEnd:结束时间
*dwTemp:当前时间
*/
//参数采用引用了,可以不用引用
float CTouchControlFreeRotation::LinearInterpolation(float& fStart, float& fEnd, DWORD& dwStart, DWORD& dwEnd, DWORD& dwTemp)
{
	float fInterpolation = 0.0f;

	float fScale = (dwTemp - dwStart) / ((dwEnd - dwStart) * 1.0f);
	fInterpolation = fStart + ((fEnd - fStart) * fScale);

	return fInterpolation;
}

Sin插值:根据开始时间、结束时间和当前时间,Sin特性计算开始值、结束值之间的一个数

//参数含义与上面的函数一样
float CTouchControlFreeRotation::SinInterpolation(float& fStart, float& fEnd, DWORD& dwStart, DWORD& dwEnd, DWORD& dwTemp)
{
	float fInterpolation = 0.0f;

	float fTemp = ((dwTemp - dwStart) / ((dwEnd - dwStart) * 1.0f)) * (float)(M_PI / 2.0f);
	fInterpolation = fStart + ((fEnd - fStart) * sin(fTemp));

	return fInterpolation;
}

震荡插值:根据开始时间、结束时间和当前时间,震荡特性计算开始值、结束值之间的一个数,这个特性是:在最终停止的位置会发生来回震荡的效果,类似钟摆最终停止的效果。(只是模拟的效果)

//nNum:震荡次数
//fWaveHeight:振幅
float CTouchControlFreeRotation::ShockInterpolation(float& fStart, float& fEnd, DWORD& dwStart, DWORD& dwEnd, DWORD& dwTemp, int nNum, float fWaveHeight)
{
	float fInterpolation = 0.0f;

	//一个周期是4,(因为在震荡之前有1/4个周期),计算单位时间
	//nNum * 4:所有震荡次数一共所占比例
	//(1 / (fWaveHeight / 100.0f))):前1/4周期所占的比例
	float	fUnit = ((dwEnd - dwStart) / ((float)(nNum * 4 + (1 / (fWaveHeight / 100.0f)))));
	//前1/4个周期的结束时间
	DWORD fPre = (DWORD)(fUnit *  (1 / (fWaveHeight / 100.0f))) + dwStart;
	//说明时间在前1/4个周期的范围内
	if (dwTemp <= fPre)
	{
		//将时间映射到 π/2到π(因为在该阶段中,速度变化应该是越来越快的)
		float fAngle = (float)((dwTemp - dwStart) / ((fPre - dwStart)* 1.0f) * (M_PI / 2) + M_PI / 2);
		//用sin模拟计算位置
		fInterpolation = fEnd + ((fStart - fEnd) * sin(fAngle));
	}
	else
	{
		//根据振幅计算最大的新的开始位置
		float fStartNew = fEnd + (fStart - fEnd) * (fWaveHeight / 100.0f);

		//得到当前时间所在阶段的开始时间和结束时间
		DWORD dwBegin = 0;
		DWORD dwStop = fPre;
		int i = 0;
		while (dwStop < dwTemp && i <= nNum)
		{
			i++;
			dwBegin = dwStop;
			dwStop = (DWORD)(fUnit * (i * 4) + fPre);;
		}
		//根据当前时间段,计算出新的开始位置
		fStartNew = (fStartNew - fEnd) * (1 - (i - 1) / ((float)nNum)) + fEnd;

		if (dwBegin != dwStop)
		{
			//将时间映射到 -π到π
			float fAngle = (float)((dwTemp - dwBegin) / ((dwStop - dwBegin)* 1.0f) * M_PI_D - M_PI);
			//用sin模拟计算位置
			fInterpolation = fEnd + ((fStartNew - fEnd) * sin(fAngle));
		}
	}

	return fInterpolation;
}