www.pudn.com > notWow.rar > Animated.h


//--------------------------------------------------------- 
//	This file is partly from WoWModelViewer's Sourc codes 
//  and made some modify  
//	 @BY : HADX 
//--------------------------------------------------------- 
#pragma once 
 
#include  
#include  
#include  
 
#include "M2Block.h" 
 
// interpolation functions 
template 
inline T interpolate(const float r, const T &v1, const T &v2) 
{ 
	return static_cast(v1*(1.0f - r) + v2*r); 
} 
 
template 
inline T interpolateHermite(const float r, const T &v1, const T &v2, const T &in, const T &out) 
{ 
	// basis functions 
	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; 
 
	// interpolation 
	return static_cast(v1*h1 + v2*h2 + in*h3 + out*h4); 
} 
 
// "linear" interpolation for quaternions should be slerp by default 
template<> 
inline D3DXQUATERNION interpolate(const float r, const D3DXQUATERNION &v1, const D3DXQUATERNION &v2) 
{ 
	D3DXQUATERNION res; 
	D3DXQuaternionSlerp(&res,&v1,&v2,r); 
	return res; 
} 
 
 
typedef std::pair AnimRange; 
 
// global time for global sequences 
extern int globalTime; 
extern int globalFrame; 
 
enum Interpolations  
{ 
	INTERPOLATION_NONE, 
	INTERPOLATION_LINEAR, 
	INTERPOLATION_HERMITE 
}; 
 
template  
class Identity  
{ 
public: 
	static const T& conv(const T& t) 
	{ 
		return t; 
	} 
}; 
 
// Convert opacity values stored as shorts to floating point 
// I wonder why Blizzard decided to save 2 bytes by doing this 
class ShortToFloat { 
public: 
	static const float conv(const short t) 
	{ 
		return t/32767.0f; 
	} 
}; 
 
/* 
	Generic animated value class: 
 
	T is the data type to animate 
	D is the data type stored in the file (by default this is the same as T) 
	Conv is a conversion object that defines T conv(D) to convert from D to T 
		(by default this is an identity function) 
	(there might be a nicer way to do this? meh meh) 
*/ 
template  > 
class Animated  
{ 
public: 
	bool used; 
	int type, seq; 
	int *globals; 
 
	std::vector ranges; 
	std::vector times; 
	std::vector data; 
 
	// for nonlinear interpolations: 
	std::vector in, out; 
 
	T getValue(unsigned int anim, unsigned int time) 
	{ 
		if (type != INTERPOLATION_NONE || data.size()>1)  
		{ 
			AnimRange range; 
 
			// obtain a time value and a data range 
			if (seq>-1)  
			{ 
				if (globals[seq]==0)  
					time = 0; 
				else  
					time = globalTime % globals[seq]; 
				range.first = 0; 
				range.second = data.size()-1; 
			}  
			else  
			{ 
				range = ranges[anim]; 
				time %= times[times.size()-1]; // I think this might not be necessary? 
			} 
 
 			if (range.first != range.second)  
			{ 
				size_t t1, t2; 
				size_t pos=0; 
				for (size_t i=range.first; i= times[i] && time < times[i+1])  
					{ 
						pos = i; 
						break; 
					} 
				} 
				t1 = times[pos]; 
				t2 = times[pos+1]; 
				float r = (time-t1)/(float)(t2-t1); 
 
				if (type == INTERPOLATION_LINEAR)  
					return interpolate(r,data[pos],data[pos+1]); 
				else if (type == INTERPOLATION_NONE)  
					return data[pos]; 
				else { 
					// INTERPOLATION_HERMITE is only used in cameras afaik? 
					return interpolateHermite(r,data[pos],data[pos+1],in[pos],out[pos]); 
				} 
			}  
			else  
			{ 
				return data[range.first]; 
			} 
		}  
		else  
		{ 
			assert(data.size() != 0); 
			return data[0]; 
		} 
	} 
 
	void init(AnimationBlock &b, char* f, int *gs) 
	{ 
		globals = gs; 
		type = b.type; 
		seq = b.seq; 
		if (seq!=-1)  
		{ 
            assert(gs); 
		} 
 
		int i; 
		used = (b.nKeys > 0); 
 
		// ranges 
		if (b.nRanges > 0)  
		{ 
			uint32 *pranges = (uint32*)(f + b.ofsRanges); 
			for (size_t i=0, k=0; i AnimatedShort;