public AnimEvaluator(Assimp.Animation anim) { LastTime = 0.0f; TicksPerSecond = anim.TicksPerSecond > 0.0f ? ( float )anim.TicksPerSecond : 920.0f; Duration = ( float )anim.DurationInTicks; Name = anim.Name; Channels = new List <AnimChannel> ( ); foreach (Assimp.NodeAnimationChannel channel in anim.NodeAnimationChannels) { AnimChannel nac = new AnimChannel(); List <VectorKey> pk = new List <VectorKey> ( ); List <QuatKey> rk = new List <QuatKey> ( ); List <VectorKey> sk = new List <VectorKey> ( ); foreach (Assimp.VectorKey k in channel.PositionKeys) { VectorKey npk = new VectorKey { Time = k.Time, Value = new OpenTK.Vector3(k.Value.X, k.Value.Y, k.Value.Z) }; pk.Add(npk); } foreach (Assimp.QuaternionKey k in channel.RotationKeys) { QuatKey nrk = new QuatKey { Time = k.Time, Value = new OpenTK.Quaternion(k.Value.X, k.Value.Y, k.Value.Z, k.Value.W) }; rk.Add(nrk); } foreach (Assimp.VectorKey s in channel.ScalingKeys) { VectorKey nsk = new VectorKey { Time = s.Time, Value = new OpenTK.Vector3(s.Value.X, s.Value.Y, s.Value.Z) }; sk.Add(nsk); } nac.Name = channel.NodeName; nac.PositionKeys = pk; nac.RotationKeys = rk; nac.ScalingKeys = sk; Channels.Add(nac); } LastPositions = Enumerable.Repeat(new MutableTuple <int, int, int> (0, 0, 0), anim.NodeAnimationChannelCount).ToList( ); Transforms = new List <List <OpenTK.Matrix4> > ( ); PlayAnimationForward = true; }
public void Evaluate(float dt, Dictionary <string, Bone> bones) { dt *= TicksPerSecond; float time = 0.0f; if (Duration > 0.0f) { time = dt % Duration; } for (int i = 0; i < Channels.Count; i++) { AnimChannel channel = Channels[i]; if (!bones.ContainsKey(channel.Name)) { Console.WriteLine("Did not find the bone node " + channel.Name); continue; } // interpolate position keyframes OpenTK.Vector3 pPosition = new OpenTK.Vector3( ); if (channel.PositionKeys.Count > 0) { int frame = (time >= LastTime) ? LastPositions[i].Item1 : 0; while (frame < channel.PositionKeys.Count - 1) { if (time < channel.PositionKeys [frame + 1].Time) { break; } frame++; } if (frame >= channel.PositionKeys.Count) { frame = 0; } int nextFrame = (frame + 1) % channel.PositionKeys.Count; VectorKey key = channel.PositionKeys[frame]; VectorKey nextKey = channel.PositionKeys[nextFrame]; double diffTime = nextKey.Time - key.Time; if (diffTime < 0.0) { diffTime += Duration; } if (diffTime > 0.0) { float factor = (float)((time - key.Time) / diffTime); pPosition = key.Value + (nextKey.Value - key.Value) * factor; } else { pPosition = key.Value; } MutableTuple <int, int, int> tl = LastPositions [i]; tl.Item1 = frame; LastPositions [i].Item1 = frame; } // interpolate rotation keyframes OpenTK.Quaternion pRot = new OpenTK.Quaternion(0, 0, 0, 1); if (channel.RotationKeys.Count > 0) { int frame = (time >= LastTime) ? LastPositions[i].Item2 : 0; while (frame < channel.RotationKeys.Count - 1) { if (time < channel.RotationKeys [frame + 1].Time) { break; } frame++; } if (frame >= channel.RotationKeys.Count) { frame = 0; } int nextFrame = (frame + 1) % channel.RotationKeys.Count; QuatKey key = channel.RotationKeys[frame]; QuatKey nextKey = channel.RotationKeys[nextFrame]; key.Value.Normalize( ); nextKey.Value.Normalize( ); double diffTime = nextKey.Time - key.Time; if (diffTime < 0.0) { diffTime += Duration; } if (diffTime > 0) { float factor = (float)((time - key.Time) / diffTime); pRot = OpenTK.Quaternion.Slerp(key.Value, nextKey.Value, factor); } else { pRot = key.Value; } LastPositions [i].Item1 = frame; } // interpolate scale keyframes OpenTK.Vector3 pscale = new OpenTK.Vector3(1); if (channel.ScalingKeys.Count > 0) { int frame = (time >= LastTime) ? LastPositions[i].Item3 : 0; while (frame < channel.ScalingKeys.Count - 1) { if (time < channel.ScalingKeys [frame + 1].Time) { break; } frame++; } if (frame >= channel.ScalingKeys.Count) { frame = 0; } LastPositions [i].Item3 = frame; } //OpenTK.Matrix4 mat = OpenTK.Matrix4.CreateFromQuaternion(pRot); // create the combined transformation matrix Assimp.Matrix4x4 mat = new Assimp.Matrix4x4(new Assimp.Quaternion(pRot.W, pRot.X, pRot.Y, pRot.Z).GetMatrix( )); mat.A1 *= pscale.X; mat.B1 *= pscale.X; mat.C1 *= pscale.X; mat.A2 *= pscale.Y; mat.B2 *= pscale.Y; mat.C2 *= pscale.Y; mat.A3 *= pscale.Z; mat.B3 *= pscale.Z; mat.C3 *= pscale.Z; mat.A4 = pPosition.X; mat.B4 = pPosition.Y; mat.C4 = pPosition.Z; // transpose to get DirectX style matrix //mat.Transpose(); //mat.Inverse(); bones [channel.Name].LocalTransform = ToTK(mat); } LastTime = time; }