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;