/* * template AnimationKey * { * DWORD keyType; * DWORD nKeys; * array TimedFloatKeys keys[nKeys]; * } * * * template TimedFloatKeys * { * DWORD time; * FloatKeys tfkeys; * } * * template FloatKeys * { * DWORD nValues; * array float values[nValues]; * } */ /// <summary> /// Imports a key frame list associated with an animation channel /// </summary> /// <param name="keyType">The type of animation keys used by the current channel</param> /// <returns>The list of key frames for the given key type in the current channel</returns> private AnimationKeyframe[] ImportAnimationKey(out int keyType) { // These keys can be rotation (0),scale(1),translation(2), or matrix(3 or 4) keys. keyType = tokens.SkipName().NextInt(); // Number of frames in channel int numFrames = tokens.NextInt(); AnimationKeyframe[] frames = new AnimationKeyframe[numFrames]; // Find the ticks per millisecond that defines how fast the animation should go double ticksPerMS = animTicksPerSecond == null ? DEFAULT_TICKS_PER_SECOND / 1000.0 : (double)animTicksPerSecond / 1000.0; // fill in the frames for (int i = 0; i < numFrames; i++) { // Create a timespan object that represents the time that the current keyframe // occurs TimeSpan time = new TimeSpan(0, 0, 0, 0, (int)(tokens.NextInt() / ticksPerMS)); // The number of keys that represents the transform for this keyframe. // Quaternions (rotation keys) have 4, // Vectors (scale and translation) have 3, // Matrices have 16 int numKeys = tokens.NextInt(); Matrix transform = new Matrix(); if (numKeys == 16) { transform = tokens.NextMatrix(); } else if (numKeys == 4) { Vector4 v = tokens.NextVector4(); Quaternion q = new Quaternion( new Vector3(-v.Y, -v.Z, -v.W), v.X); transform = Matrix.CreateFromQuaternion(q); } else if (numKeys == 3) { Vector3 v = tokens.NextVector3(); if (keyType == 1) { Matrix.CreateScale(ref v, out transform); } else { Matrix.CreateTranslation(ref v, out transform); } } tokens.SkipToken(); frames[i] = new AnimationKeyframe(time, transform); } tokens.SkipToken(); return(frames); }
// "This template is instantiated on a per-mesh basis. Within a mesh, a sequence of n // instances of this template will appear, where n is the number of bones (X file frames) // that influence the vertices in the mesh. Each instance of the template basically defines // the influence of a particular bone on the mesh. There is a list of vertex indices, and a // corresponding list of weights. // template SkinWeights // { // STRING transformNodeName; // DWORD nWeights; // array DWORD vertexIndices[nWeights]; // array float weights[nWeights]; // Matrix4x4 matrixOffset; // } // - The name of the bone whose influence is being defined is transformNodeName, // and nWeights is the number of vertices affected by this bone. // - The vertices influenced by this bone are contained in vertexIndices, and the weights for // each of the vertices influenced by this bone are contained in weights. // - The matrix matrixOffset transforms the mesh vertices to the space of the bone. When concatenated // to the bone's transform, this provides the world space coordinates of the mesh as affected by the bone." // (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ // directx9_c/dx9_graphics_reference_x_file_format_templates.asp) // // Reads in a bone that contains skin weights. It then adds one bone weight // to every vertex that is influenced by ths bone, which contains the name of the bone and the // weight. public void ImportSkinWeights() { isSkinned = true; string boneName = tokens.SkipName().NextString(); // an influence is an index to a vertex that is affected by the current bone int numInfluences = tokens.NextInt(); List <int> influences = new List <int>(); List <float> weights = new List <float>(); for (int i = 0; i < numInfluences; i++) { influences.Add(tokens.NextInt()); } for (int i = 0; i < numInfluences; i++) { weights.Add(tokens.NextFloat()); if (weights[i] == 0) { influences[i] = -1; } } influences.RemoveAll(delegate(int i) { return(i == -1); }); weights.RemoveAll(delegate(float f) { return(f == 0); }); // Add the matrix that transforms the vertices to the space of the bone. // we will need this for skinned animation. Matrix blendOffset = tokens.NextMatrix(); ContentUtil.ReflectMatrix(ref blendOffset); skinTransformDictionary.Add(boneName, blendOffset); SkinTransformContent trans = new SkinTransformContent(); trans.BoneName = boneName; trans.Transform = blendOffset; skinTransforms.Add(trans); // end of skin weights tokens.SkipToken(); // add a new name/weight pair to every vertex influenced by the bone for (int i = 0; i < influences.Count; i++) { skinInfo[influences[i]].Add(new BoneWeight(boneName, weights[i])); } }