Bones are used to animate characters. They hold rotation and translation data.
Example #1
0
        /// <summary>
        /// Computes the absolute position for all the bones in this skeleton.
        /// </summary>
        /// <param name="bone">The bone to start with, should always be the ROOT bone.</param>
        /// <param name="world">A world matrix to use in the calculation.</param>
        public void ComputeBonePositions(Bone bone, Matrix world)
        {
            var translateMatrix = Matrix.CreateTranslation(bone.Translation);
            var rotationMatrix = Matrix.CreateFromQuaternion(bone.Rotation);

            var myWorld = (rotationMatrix * translateMatrix)*world;
            bone.AbsolutePosition = Vector3.Transform(Vector3.Zero, myWorld);
            bone.AbsoluteMatrix = myWorld;

            foreach (var child in bone.Children)
            {
                ComputeBonePositions(child, myWorld);
            }
        }
Example #2
0
 /// <summary>
 /// Clones this bone.
 /// </summary>
 /// <returns>A Bone instance with the same values as this one.</returns>
 public Bone Clone()
 {
     var result = new Bone
     {
         Unknown = this.Unknown,
         Name = this.Name,
         ParentName = this.ParentName,
         HasProps = this.HasProps,
         Properties = this.Properties,
         Translation = this.Translation,
         Rotation = this.Rotation,
         CanTranslate = this.CanTranslate,
         CanRotate = this.CanRotate,
         CanBlend = this.CanBlend,
         WiggleValue = this.WiggleValue,
         WigglePower = this.WigglePower,
         Index = this.Index
     };
     return result;
 }
Example #3
0
        //TODO: assumes that skeleton will be same configuration for all bindings of this mesh.
        //If any meshes are used by pets and avatars(???) or we implement children this will need
        //to be changed to support binds to multiple SKEL bases.
        /// <summary>
        /// Transforms the verticies making up this mesh into
        /// the designated bone positions.
        /// </summary>
        /// <param name="bone">The bone to start with. Should always be the ROOT bone.</param>
        /// 
        public void Prepare(Bone bone)
        {
            if (Prepared) return;
            var binding = BoneBindings.FirstOrDefault(x => x.BoneName.Equals(bone.Name, StringComparison.InvariantCultureIgnoreCase));
            if (binding != null)
            {
                for (var i = 0; i < binding.RealVertexCount; i++)
                {
                    var vertexIndex = binding.FirstRealVertex + i;
                    VertexBuffer[vertexIndex].Parameters.X = bone.Index;
                }

                for (var i = 0; i < binding.BlendVertexCount; i++)
                {
                    var blendVertexIndex = binding.FirstBlendVertex + i;
                    BlendVertBoneIndices[blendVertexIndex] = bone.Index;

                }
            }

            foreach (var child in bone.Children)
            {
                Prepare(child);
            }

            if (bone.Name.Equals("ROOT", StringComparison.InvariantCultureIgnoreCase))
            {
                for (int i = 0; i < BlendData.Length; i++)
                {
                    var data = BlendData[i];
                    var vert = BlendVertBoneIndices[i];

                    VertexBuffer[data.OtherVertex].Parameters.Y = BlendVertBoneIndices[i];
                    VertexBuffer[data.OtherVertex].Parameters.Z = data.Weight;
                    VertexBuffer[data.OtherVertex].BvPosition = BlendVerts[i];
                }

                InvalidateMesh();
                Prepared = true;
            }
        }
Example #4
0
        /// <summary>
        /// Reads a skeleton from a stream.
        /// </summary>
        /// <param name="stream">A Stream instance holding a skeleton.</param>
        public void Read(Stream stream)
        {
            using (var io = IoBuffer.FromStream(stream))
            {
                var version = io.ReadUInt32();
                Name = io.ReadPascalString();

                var boneCount = io.ReadInt16();

                Bones = new Bone[boneCount];
                for (var i = 0; i < boneCount; i++)
                {
                    Bone bone = ReadBone(io);
                    bone.Index = i;
                    Bones[i] = bone;
                }

                /** Construct tree **/
                foreach (var bone in Bones)
                {
                    bone.Children = Bones.Where(x => x.ParentName == bone.Name).ToArray();
                }
                RootBone = Bones.FirstOrDefault(x => x.ParentName == "NULL");
                ComputeBonePositions(RootBone, Matrix.Identity);
            }
        }
Example #5
0
        /// <summary>
        /// Reads a bone from a IOBuffer.
        /// </summary>
        /// <param name="reader">An IOBuffer instance used to read from a stream holding a skeleton.</param>
        /// <returns>A Bone instance.</returns>
        private Bone ReadBone(IoBuffer reader)
        {
            var bone = new Bone();
            bone.Unknown = reader.ReadInt32();
            bone.Name = reader.ReadPascalString();
            bone.ParentName = reader.ReadPascalString();
            bone.HasProps = reader.ReadByte();
            if (bone.HasProps != 0)
            {
                var propertyCount = reader.ReadInt32();
                var property = new PropertyListItem();

                for (var i = 0; i < propertyCount; i++)
                {
                    var pairCount = reader.ReadInt32();
                    for (var x = 0; x < pairCount; x++)
                    {
                        property.KeyPairs.Add(new KeyValuePair<string, string>(
                            reader.ReadPascalString(),
                            reader.ReadPascalString()
                        ));
                    }
                }
                bone.Properties.Add(property);
            }

            var xx = -reader.ReadFloat();
            bone.Translation = new Vector3(
                xx,
                reader.ReadFloat(),
                reader.ReadFloat()
            );
            bone.Rotation = new Quaternion(
                reader.ReadFloat(),
                -reader.ReadFloat(),
                -reader.ReadFloat(),
                -reader.ReadFloat()
            );
            bone.CanTranslate = reader.ReadInt32();
            bone.CanRotate = reader.ReadInt32();
            bone.CanBlend = reader.ReadInt32();
            bone.WiggleValue = reader.ReadFloat();
            bone.WigglePower = reader.ReadFloat();
            return bone;
        }