⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 interpolate.h

📁 3D游戏展示程序
💻 H
字号:
//--------------------------------------------------
//  Desc: Interpolate
//  Date: 2007.4.3 /update
//  Author: Artsylee
//
//  From: WOW Model Viewer
//  I just coding in my own ways!
//
//--------------------------------------------------

#ifndef _INTERPOLATE_
#define _INTERPOLATE_

#include <vector>
#include <assert.h>
#include "Vector3D.h"
#include "Quaternion.h"
#include "M2Header.h"

using namespace std;

// global time for global sequences
extern unsigned long g_GlobalTime;

enum InterpolationType
{
	INTERPOLATION_NONE,
	INTERPOLATION_LINEAR,
	INTERPOLATION_HERMITE
};

template<class T>
inline T InterpolateLinear(const float r, const T &v1, const T &v2)
{
	return static_cast<T>(v1*(1.0f - r) + v2*r);
}

template<class T>
inline T InterpolateHermite(const float r, const T &v1, const T &v2, const T &in, const T &out)
{
	float h1 = 2.0f*r*r*r - 3.0f*r*r + 1.0f;
	float h2 = -2.0f*r*r*r + 3.0f*r*r;
	float h3 = r*r*r - 2.0f*r*r + r;
	float h4 = r*r*r - r*r;

	return static_cast<T>(v1*h1 + v2*h2 + in*h3 + out*h4);
}

template<>
inline Quaternion InterpolateLinear<Quaternion>(const float r, const Quaternion &v1, const Quaternion &v2)
{
	return Slerp(r, v1, v2);
}

template<>
inline D3DXQUATERNION InterpolateLinear<D3DXQUATERNION>(const float r, const D3DXQUATERNION &v1, const D3DXQUATERNION &v2)
{
	D3DXQUATERNION quatRet;
	D3DXQuaternionSlerp(&quatRet, &v1, &v2, r);
	return quatRet;
}

template<class T>
class Identity 
{
public:
	static const T& conv(const T &t)	{	return t;	}
};

class ShortToFloat 
{
public:
	static const float conv(const short t)	{	return t/32767.0f;	}
};

typedef std::pair<size_t, size_t> AnimRange;

template<class T, class D = T, class Conv = Identity<T> >
class Animated 
{
public:
	bool	m_bUsed;
	int		m_InterType;
	int		m_Sequence;
	int*	m_pSequence;

	std::vector<AnimRange>		m_Ranges;
	std::vector<unsigned int>	m_Times;
	std::vector<T>	m_Data;
	std::vector<T>	m_In, m_Out;

	void Init(AnimationBlock &block, uint8* pData, int *pSequence)
	{
		m_pSequence = pSequence;
		m_InterType = block.type;
		m_Sequence = block.seq;
		if(m_Sequence !=-1 )	{	assert(pSequence);	}
		m_bUsed = (block.nKeys > 0);

		// ranges
		if(block.nRanges > 0) 
		{
			uint32 *pRanges = (uint32*)(pData+block.ofsRanges);
			for(size_t i=0, k=0; i<block.nRanges; i++) 
			{
				AnimRange range;
				range.first = pRanges[k++];
				range.second = pRanges[k++];
				m_Ranges.push_back(range);
			}
		} 
		else if(m_InterType!=0 && m_Sequence==-1) 
		{
			AnimRange range;
			range.first = 0;
			range.second = block.nKeys - 1;
			m_Ranges.push_back(range);
		}

		// times
		assert(block.nTimes == block.nKeys);
		uint32 *pTimes = (uint32*)(pData+block.ofsTimes);
		for(size_t i=0; i<block.nTimes; i++) 
		{
			m_Times.push_back(pTimes[i]);
		}

		// key frames
		assert((D*)(pData+block.ofsKeys));
		D *pKeys = (D*)(pData+block.ofsKeys);
		switch(m_InterType) 
		{
		case INTERPOLATION_NONE:
		case INTERPOLATION_LINEAR:
			{
				for(size_t i=0; i<block.nKeys; i++) 
					m_Data.push_back(Conv::conv(pKeys[i]));
			}
			break;
		case INTERPOLATION_HERMITE:
			{
				for(size_t i=0; i<block.nKeys; i++) 
				{
					m_Data.push_back(Conv::conv(pKeys[i*3+0]));
					m_In.push_back(Conv::conv(pKeys[i*3+1]));
					m_Out.push_back(Conv::conv(pKeys[i*3+2]));
				}
			}
			break;
		}
		if(m_Data.size()==0) 
		{
			m_Data.push_back(T());
		}
	}

	void Fix(T Fixfunc(const T&))
	{
		switch(m_InterType) 
		{
		case INTERPOLATION_NONE:
		case INTERPOLATION_LINEAR:
			{
				for(size_t i=0; i<m_Data.size(); i++) 
				{
					m_Data[i] = Fixfunc(m_Data[i]);
				}
			}
			break;
		case INTERPOLATION_HERMITE:
			{
				for(size_t i=0; i<m_Data.size(); i++) 
				{
					m_Data[i] = Fixfunc(m_Data[i]);
					m_In[i] = Fixfunc(m_In[i]);
					m_Out[i] = Fixfunc(m_Out[i]);
				}
			}
			break;
		}
	}

	T GetValue(unsigned int anim, unsigned int time)
	{
		if(m_InterType != INTERPOLATION_NONE || m_Data.size()>1) 
		{
			AnimRange range;

			// obtain a time value and a data range
			if(m_Sequence>-1) 
			{
				if(m_pSequence[m_Sequence]==0) 
					time = 0;
				else 
					time = g_GlobalTime % m_pSequence[m_Sequence];
				range.first = 0;
				range.second = m_Data.size()-1;
			} 
			else 
			{
				range = m_Ranges[anim];
				time %= m_Times[m_Times.size()-1];
			}

			if(range.first != range.second) 
			{
				size_t time1, time2;
				size_t pos = 0;
				for(size_t i=range.first; i<range.second; i++) 
				{
					if(time >= m_Times[i] && time < m_Times[i+1]) 
					{
						pos = i;
						break;
					}
				}
				time1 = m_Times[pos];
				time2 = m_Times[pos+1];
				float r = (time-time1)/(float)(time2-time1);

				if(m_InterType == INTERPOLATION_LINEAR) 
					return InterpolateLinear<T>(r, m_Data[pos], m_Data[pos+1]);
				else if(m_InterType == INTERPOLATION_NONE) 
					return m_Data[pos];
				else
					return InterpolateHermite<T>(r, m_Data[pos], m_Data[pos+1], m_In[pos], m_Out[pos]);
			} 
			else 
			{
				return m_Data[range.first];
			}
		} 
		else 
		{
		//	if(m_Data.size() == 0)
		//		return 0;
		//	else
			return m_Data[0];
		}
	}
};

typedef Animated<float, short, ShortToFloat> AnimatedShort;


#endif // _INTERPOLATE_

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -