public void ReadBCF(BCFReadProxy io) { Name = io.ReadPascalString(); var type = io.ReadInt32(); var zero = io.ReadInt32(); var numBindings = io.ReadUInt32(); Bindings = new AppearanceBinding[numBindings]; for (var i = 0; i < numBindings; i++) { //bindings are included verbatim here. var bnd = new Binding(); bnd.Bone = io.ReadPascalString(); bnd.MeshName = io.ReadPascalString(); io.ReadInt32(); io.ReadInt32(); Bindings[i] = new AppearanceBinding { RealBinding = bnd }; } }
/// <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(BCFReadProxy reader, bool bcf) { var bone = new Bone(); if (!bcf) { bone.Unknown = reader.ReadInt32(); } bone.Name = reader.ReadPascalString(); bone.ParentName = reader.ReadPascalString(); bone.HasProps = bcf || reader.ReadByte() > 0; if (bcf && bone.Name == "") { return(null); } if (bone.HasProps) { 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); }
/// <summary> /// Reads a skeleton from a stream. /// </summary> /// <param name="stream">A Stream instance holding a skeleton.</param> public void Read(BCFReadProxy io, bool bcf) { if (!bcf) { 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, bcf); if (bone == null) { i--; continue; } 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); }
/// <summary> /// Reads a property list from a stream. /// </summary> /// <param name="io">IOBuffer instance used to read an animation.</param> /// <returns>A PropertyList instance.</returns> private PropertyList ReadPropertyList(BCFReadProxy io, bool shortPairs) { var propsCount = (shortPairs) ? 1 : io.ReadUInt32(); var result = new PropertyListItem[propsCount]; for (var y = 0; y < propsCount; y++) { var item = new PropertyListItem(); var pairsCount = io.ReadUInt32(); for (var z = 0; z < pairsCount; z++) { item.KeyPairs.Add(new KeyValuePair <string, string>( io.ReadPascalString(), io.ReadPascalString() )); } result[y] = item; } return(new PropertyList { Items = result }); }
/// <summary> /// Reads a mesh from a stream. /// </summary> /// <param name="stream">A Stream instance holding a mesh.</param> <param name="bmf">If this stream contains a .bmf file (rather than TSO .mesh).</param> public void Read(BCFReadProxy io, bool bmf) { if (bmf) { SkinName = io.ReadPascalString(); TextureName = io.ReadPascalString(); } else { var version = io.ReadInt32(); } var boneCount = io.ReadInt32(); var boneNames = new string[boneCount]; for (var i = 0; i < boneCount; i++) { boneNames[i] = io.ReadPascalString(); } var faceCount = io.ReadInt32(); NumPrimitives = faceCount; IndexBuffer = new short[faceCount * 3]; int offset = 0; for (var i = 0; i < faceCount; i++) { IndexBuffer[offset++] = (short)io.ReadInt32(); IndexBuffer[offset++] = (short)io.ReadInt32(); IndexBuffer[offset++] = (short)io.ReadInt32(); } /** Bone bindings **/ var bindingCount = io.ReadInt32(); BoneBindings = new BoneBinding[bindingCount]; for (var i = 0; i < bindingCount; i++) { BoneBindings[i] = new BoneBinding { BoneIndex = io.ReadInt32(), FirstRealVertex = io.ReadInt32(), RealVertexCount = io.ReadInt32(), FirstBlendVertex = io.ReadInt32(), BlendVertexCount = io.ReadInt32() }; BoneBindings[i].BoneName = boneNames[Math.Min(boneNames.Length - 1, BoneBindings[i].BoneIndex)]; } var realVertexCount = io.ReadInt32(); VertexBuffer = new VitaboyVertex[realVertexCount]; for (var i = 0; i < realVertexCount; i++) { VertexBuffer[i].TextureCoordinate.X = io.ReadFloat(); VertexBuffer[i].TextureCoordinate.Y = io.ReadFloat(); } /** Blend data **/ var blendVertexCount = io.ReadInt32(); BlendData = new BlendData[blendVertexCount]; for (var i = 0; i < blendVertexCount; i++) { if (io is IoBuffer) { BlendData[i] = new BlendData { Weight = (float)io.ReadInt32() / 0x8000, OtherVertex = io.ReadInt32() }; } else { BlendData[i] = new BlendData { OtherVertex = io.ReadInt32(), Weight = (float)io.ReadInt32() / 0x8000 }; } } var realVertexCount2 = io.ReadInt32(); for (int i = 0; i < realVertexCount; i++) { VertexBuffer[i].Position = new Microsoft.Xna.Framework.Vector3( -io.ReadFloat(), io.ReadFloat(), io.ReadFloat() ); VertexBuffer[i].Normal = new Microsoft.Xna.Framework.Vector3( -io.ReadFloat(), io.ReadFloat(), io.ReadFloat() ); if (VertexBuffer[i].Normal == Vector3.Zero) { VertexBuffer[i].Normal = new Vector3(0, 1, 0); } } BlendVerts = new Vector3[blendVertexCount]; for (int i = 0; i < blendVertexCount; i++) { BlendVerts[i] = new Vector3( -io.ReadFloat(), io.ReadFloat(), io.ReadFloat() ); var normal = new Vector3( -io.ReadFloat(), io.ReadFloat(), io.ReadFloat() ); //todo: read this in somewhere and use it for lighting. } BlendVertBoneIndices = new int[blendVertexCount]; }
/// <summary> /// Reads an animation from a stream. /// </summary> /// <param name="stream">The Stream instance to read from.</param> public void Read(BCFReadProxy io, bool bcf) { if (!bcf) { var version = io.ReadUInt32(); } if (bcf) { Name = io.ReadPascalString(); XSkillName = io.ReadPascalString(); } else { Name = io.ReadLongPascalString(); } Duration = io.ReadFloat(); Distance = io.ReadFloat(); IsMoving = (bcf)?((byte)io.ReadInt32()):io.ReadByte(); TranslationCount = io.ReadUInt32(); if (!bcf) { Translations = new Vector3[TranslationCount]; for (var i = 0; i < TranslationCount; i++) { Translations[i] = new Vector3 { X = -io.ReadFloat(), Y = io.ReadFloat(), Z = io.ReadFloat() }; } } RotationCount = io.ReadUInt32(); if (!bcf) { Rotations = new Quaternion[RotationCount]; for (var i = 0; i < RotationCount; i++) { Rotations[i] = new Quaternion { X = io.ReadFloat(), Y = -io.ReadFloat(), Z = -io.ReadFloat(), W = -io.ReadFloat() }; } } var motionCount = io.ReadUInt32(); Motions = new AnimationMotion[motionCount]; for (var i = 0; i < motionCount; i++) { var motion = new AnimationMotion(); if (!bcf) { var unknown = io.ReadUInt32(); } motion.BoneName = io.ReadPascalString(); motion.FrameCount = io.ReadUInt32(); motion.Duration = io.ReadFloat(); motion.HasTranslation = (((bcf) ? io.ReadInt32() : io.ReadByte()) == 1); motion.HasRotation = (((bcf) ? io.ReadInt32() : io.ReadByte()) == 1); motion.FirstTranslationIndex = io.ReadUInt32(); motion.FirstRotationIndex = io.ReadUInt32(); var hasPropsList = bcf || io.ReadByte() == 1; if (hasPropsList) { var propListCount = io.ReadUInt32(); var props = new PropertyList[propListCount]; for (var x = 0; x < propListCount; x++) { props[x] = ReadPropertyList(io, bcf); } motion.Properties = props; } var hasTimeProps = bcf || io.ReadByte() == 1; if (hasTimeProps) { var timePropsListCount = io.ReadUInt32(); var timePropsList = new TimePropertyList[timePropsListCount]; for (var x = 0; x < timePropsListCount; x++) { var list = new TimePropertyList(); var timePropsCount = io.ReadUInt32(); list.Items = new TimePropertyListItem[timePropsCount]; for (var y = 0; y < timePropsCount; y++) { var id = io.ReadUInt32(); list.Items[y] = new TimePropertyListItem { ID = id, Properties = ReadPropertyList(io, bcf) }; } timePropsList[x] = list; } motion.TimeProperties = timePropsList; } Motions[i] = motion; } }