コード例 #1
0
        public void ReadStrings01(ByteOrder order, bool dynamicRead)
        {
            var value1 = "Length_Prefixed_String_#01!";
            var value2 = "Fixed_Length_String_#01!";
            var value3 = "Null_Terminated_String_#01!";

            using (var stream = new MemoryStream(new byte[500]))
                using (var reader = new EndianReader(stream, order))
                    using (var writer = new EndianWriter(stream, order))
                    {
                        reader.DynamicReadEnabled = dynamicRead;
                        writer.Write(value1);

                        stream.Position = 0x20;
                        writer.WriteStringFixedLength(value2, 32);

                        stream.Position = 0x40;
                        writer.WriteStringNullTerminated(value3);

                        stream.Position = 0x60;
                        writer.Write(value1, ByteOrder.LittleEndian);

                        stream.Position = 0x80;
                        writer.Write(value1, ByteOrder.BigEndian);

                        stream.Position = 0;
                        var obj = reader.ReadObject <DataClass05>();

                        Assert.AreEqual(value1, obj.Property1);

                        Assert.AreEqual(value2, obj.Property2);

                        Assert.AreEqual(32, obj.Property3.Length);
                        Assert.IsTrue(obj.Property3.StartsWith(value2));

                        Assert.AreEqual(value3, obj.Property4);
                        Assert.AreEqual(value3, obj.Property5);

                        Assert.AreEqual(value1, obj.Property6);
                        Assert.AreEqual(value1, obj.Property7);
                    }
        }
コード例 #2
0
        public void NullTerminated(ByteOrder order)
        {
            var value1 = "Null_Terminated_String_#01!";

            using (var stream = new MemoryStream(new byte[64]))
                using (var reader = new EndianReader(stream, order))
                    using (var writer = new EndianWriter(stream, order))
                    {
                        writer.WriteStringNullTerminated(value1);
                        Assert.AreEqual(value1.Length + 1, stream.Position);

                        stream.Position = 0;
                        var value2 = reader.ReadNullTerminatedString();
                        Assert.AreEqual(value1.Length + 1, stream.Position);
                        Assert.AreEqual(value1, value2);

                        stream.Position = 0;
                        value2          = reader.ReadNullTerminatedString(64);
                        Assert.AreEqual(64, stream.Position);
                        Assert.AreEqual(value1, value2);
                    }
        }
コード例 #3
0
ファイル: Extensions.cs プロジェクト: Vegetal-Pole/Adjutant
        public static void WriteAMF(this IGeometryModel model, string fileName, float scale)
        {
            if (!Directory.GetParent(fileName).Exists)
            {
                Directory.GetParent(fileName).Create();
            }
            if (!fileName.EndsWith(".amf", StringComparison.CurrentCultureIgnoreCase))
            {
                fileName += ".amf";
            }

            using (var fs = new FileStream(fileName, FileMode.Create, FileAccess.Write))
                using (var bw = new EndianWriter(fs, ByteOrder.LittleEndian))
                {
                    var dupeDic = new Dictionary <int, long>();

                    var validRegions = model.Regions
                                       .Select(r => new { r.Name, Permutations = r.Permutations.Where(p => model.Meshes[p.MeshIndex].Submeshes.Count > 0).ToList() })
                                       .Where(r => r.Permutations.Count > 0)
                                       .ToList();

                    var fauxMeshes = validRegions.SelectMany(r => r.Permutations)
                                     .Where(p => p.MeshCount > 1)
                                     .GroupBy(p => p.MeshIndex)
                                     .ToDictionary(g => g.Key, g => new MultiMesh(model, g.Key, g.First().MeshCount));

                    #region Address Lists
                    var headerAddressList = new List <long>();
                    var headerValueList   = new List <long>();

                    var markerAddressList = new List <long>();
                    var markerValueList   = new List <long>();

                    var permAddressList = new List <long>();
                    var permValueList   = new List <long>();

                    var vertAddressList = new List <long>();
                    var vertValueList   = new List <long>();

                    var indxAddressList = new List <long>();
                    var indxValueList   = new List <long>();

                    var meshAddressList = new List <long>();
                    var meshValueList   = new List <long>();
                    #endregion

                    #region Header
                    bw.Write("AMF!".ToCharArray());
                    bw.Write(2.0f);
                    bw.WriteStringNullTerminated(model.Name ?? string.Empty);

                    bw.Write(model.Nodes.Count);
                    headerAddressList.Add(bw.BaseStream.Position);
                    bw.Write(0);

                    bw.Write(model.MarkerGroups.Count);
                    headerAddressList.Add(bw.BaseStream.Position);
                    bw.Write(0);

                    bw.Write(validRegions.Count);
                    headerAddressList.Add(bw.BaseStream.Position);
                    bw.Write(0);

                    bw.Write(model.Materials.Count);
                    headerAddressList.Add(bw.BaseStream.Position);
                    bw.Write(0);
                    #endregion

                    #region Nodes
                    headerValueList.Add(bw.BaseStream.Position);
                    foreach (var node in model.Nodes)
                    {
                        bw.WriteStringNullTerminated(node.Name);
                        bw.Write(node.ParentIndex);
                        bw.Write(node.FirstChildIndex);
                        bw.Write(node.NextSiblingIndex);
                        bw.Write(node.Position.X * scale);
                        bw.Write(node.Position.Y * scale);
                        bw.Write(node.Position.Z * scale);
                        bw.Write(node.Rotation.X);
                        bw.Write(node.Rotation.Y);
                        bw.Write(node.Rotation.Z);
                        bw.Write(node.Rotation.W);
                    }
                    #endregion

                    #region Marker Groups
                    headerValueList.Add(bw.BaseStream.Position);
                    foreach (var group in model.MarkerGroups)
                    {
                        bw.WriteStringNullTerminated(group.Name);
                        bw.Write(group.Markers.Count);
                        markerAddressList.Add(bw.BaseStream.Position);
                        bw.Write(0);
                    }
                    #endregion

                    #region Markers
                    foreach (var group in model.MarkerGroups)
                    {
                        markerValueList.Add(bw.BaseStream.Position);
                        foreach (var marker in group.Markers)
                        {
                            bw.Write(marker.RegionIndex);
                            bw.Write(marker.PermutationIndex);
                            bw.Write((short)marker.NodeIndex);
                            bw.Write(marker.Position.X * scale);
                            bw.Write(marker.Position.Y * scale);
                            bw.Write(marker.Position.Z * scale);
                            bw.Write(marker.Rotation.X);
                            bw.Write(marker.Rotation.Y);
                            bw.Write(marker.Rotation.Z);
                            bw.Write(marker.Rotation.W);
                        }
                    }
                    #endregion

                    #region Regions
                    headerValueList.Add(bw.BaseStream.Position);
                    foreach (var region in validRegions)
                    {
                        bw.WriteStringNullTerminated(region.Name);
                        bw.Write(region.Permutations.Count);
                        permAddressList.Add(bw.BaseStream.Position);
                        bw.Write(0);
                    }
                    #endregion

                    #region Permutations
                    foreach (var region in validRegions)
                    {
                        permValueList.Add(bw.BaseStream.Position);
                        foreach (var perm in region.Permutations)
                        {
                            var part = fauxMeshes.ContainsKey(perm.MeshIndex)
                            ? fauxMeshes[perm.MeshIndex]
                            : model.Meshes[perm.MeshIndex];

                            bw.WriteStringNullTerminated(perm.Name);
                            bw.Write((byte)part.VertexWeights);
                            bw.Write(part.NodeIndex ?? byte.MaxValue);

                            bw.Write(part.Vertices.Count);
                            vertAddressList.Add(bw.BaseStream.Position);
                            bw.Write(0);

                            int count = 0;
                            foreach (var submesh in part.Submeshes)
                            {
                                var indices = part.Indicies.Skip(submesh.IndexStart).Take(submesh.IndexLength);
                                if (part.IndexFormat == IndexFormat.TriangleStrip)
                                {
                                    indices = Unstrip(indices);
                                }

                                count += indices.Count() / 3;
                            }

                            bw.Write(count);
                            indxAddressList.Add(bw.BaseStream.Position);
                            bw.Write(0);

                            bw.Write(part.Submeshes.Count);
                            meshAddressList.Add(bw.BaseStream.Position);
                            bw.Write(0);

                            if (perm.Transform.IsIdentity && perm.TransformScale == 1)
                            {
                                bw.Write(float.NaN);
                            }
                            else
                            {
                                bw.Write(perm.TransformScale);
                                bw.Write(perm.Transform.M11);
                                bw.Write(perm.Transform.M12);
                                bw.Write(perm.Transform.M13);
                                bw.Write(perm.Transform.M21);
                                bw.Write(perm.Transform.M22);
                                bw.Write(perm.Transform.M23);
                                bw.Write(perm.Transform.M31);
                                bw.Write(perm.Transform.M32);
                                bw.Write(perm.Transform.M33);
                                bw.Write(perm.Transform.M41);
                                bw.Write(perm.Transform.M42);
                                bw.Write(perm.Transform.M43);
                            }
                        }
                    }
                    #endregion

                    #region Vertices
                    var emptyVector = new RealVector3D();

                    foreach (var region in validRegions)
                    {
                        foreach (var perm in region.Permutations)
                        {
                            var part = fauxMeshes.ContainsKey(perm.MeshIndex)
                            ? fauxMeshes[perm.MeshIndex]
                            : model.Meshes[perm.MeshIndex];

                            var scale1 = perm.Transform.IsIdentity && perm.TransformScale == 1 ? scale : 1;

                            long address;
                            if (dupeDic.TryGetValue(perm.MeshIndex, out address))
                            {
                                vertValueList.Add(address);
                                continue;
                            }
                            else
                            {
                                dupeDic.Add(perm.MeshIndex, bw.BaseStream.Position);
                            }

                            vertValueList.Add(bw.BaseStream.Position);

                            IXMVector vector;
                            var       vertices = part.BoundsIndex >= 0 ? part.Vertices.Select(v => (IVertex) new CompressedVertex(v, model.Bounds[part.BoundsIndex.Value])) : part.Vertices;
                            foreach (var vert in vertices)
                            {
                                vector = vert.Position.Count > 0 ? vert.Position[0] : emptyVector;
                                bw.Write(vector.X * scale1);
                                bw.Write(vector.Y * scale1);
                                bw.Write(vector.Z * scale1);

                                vector = vert.Normal.Count > 0 ? vert.Normal[0] : emptyVector;
                                bw.Write(vector.X);
                                bw.Write(vector.Y);
                                bw.Write(vector.Z);

                                vector = vert.TexCoords.Count > 0 ? vert.TexCoords[0] : emptyVector;
                                bw.Write(vector.X);
                                bw.Write(1 - vector.Y);

                                if (part.VertexWeights == VertexWeights.Rigid)
                                {
                                    IXMVector i;
                                    var       indices = new List <int>();
                                    i = vert.BlendIndices.Count > 0 ? vert.BlendIndices[0] : emptyVector;

                                    if (!indices.Contains((int)i.X) && i.X != 0)
                                    {
                                        indices.Add((int)i.X);
                                    }
                                    if (!indices.Contains((int)i.Y) && i.X != 0)
                                    {
                                        indices.Add((int)i.Y);
                                    }
                                    if (!indices.Contains((int)i.Z) && i.X != 0)
                                    {
                                        indices.Add((int)i.Z);
                                    }
                                    if (!indices.Contains((int)i.W) && i.X != 0)
                                    {
                                        indices.Add((int)i.W);
                                    }

                                    if (indices.Count == 0)
                                    {
                                        indices.Add(0);
                                    }

                                    foreach (int index in indices)
                                    {
                                        bw.Write((byte)index);
                                    }

                                    if (indices.Count < 4)
                                    {
                                        bw.Write(byte.MaxValue);
                                    }
                                }
                                else if (part.VertexWeights == VertexWeights.Skinned)
                                {
                                    var indices = (vert.BlendIndices.Count > 0 ? vert.BlendIndices[0] : emptyVector).AsEnumerable().ToArray();
                                    var weights = (vert.BlendWeight.Count > 0 ? vert.BlendWeight[0] : emptyVector).AsEnumerable().ToArray();

                                    var count = weights.Count(w => w > 0);

                                    if (count == 0)
                                    {
                                        bw.Write((byte)0);
                                        bw.Write((byte)255);
                                        bw.Write(0);
                                        continue;
                                        //throw new Exception("no weights on a weighted node. report this.");
                                    }

                                    for (int i = 0; i < 4; i++)
                                    {
                                        if (weights[i] > 0)
                                        {
                                            bw.Write((byte)indices[i]);
                                        }
                                    }

                                    if (count != 4)
                                    {
                                        bw.Write(byte.MaxValue);
                                    }

                                    foreach (var w in weights.Where(w => w > 0))
                                    {
                                        bw.Write(w);
                                    }
                                }
                            }
                        }
                    }
                    #endregion

                    #region Indices
                    dupeDic.Clear();
                    foreach (var region in validRegions)
                    {
                        foreach (var perm in region.Permutations)
                        {
                            var part = fauxMeshes.ContainsKey(perm.MeshIndex)
                            ? fauxMeshes[perm.MeshIndex]
                            : model.Meshes[perm.MeshIndex];

                            long address;
                            if (dupeDic.TryGetValue(perm.MeshIndex, out address))
                            {
                                indxValueList.Add(address);
                                continue;
                            }
                            else
                            {
                                dupeDic.Add(perm.MeshIndex, bw.BaseStream.Position);
                            }

                            indxValueList.Add(bw.BaseStream.Position);

                            foreach (var submesh in part.Submeshes)
                            {
                                var indices = part.Indicies.Skip(submesh.IndexStart).Take(submesh.IndexLength);
                                if (part.IndexFormat == IndexFormat.TriangleStrip)
                                {
                                    indices = Unstrip(indices);
                                }

                                foreach (var index in indices)
                                {
                                    if (part.Vertices.Count > ushort.MaxValue)
                                    {
                                        bw.Write(index);
                                    }
                                    else
                                    {
                                        bw.Write((ushort)index);
                                    }
                                }
                            }
                        }
                    }
                    #endregion

                    #region Submeshes
                    foreach (var region in validRegions)
                    {
                        foreach (var perm in region.Permutations)
                        {
                            meshValueList.Add(bw.BaseStream.Position);

                            var part = fauxMeshes.ContainsKey(perm.MeshIndex)
                            ? fauxMeshes[perm.MeshIndex]
                            : model.Meshes[perm.MeshIndex];

                            int currentPosition = 0;
                            foreach (var mesh in part.Submeshes)
                            {
                                var indices = part.Indicies.Skip(mesh.IndexStart).Take(mesh.IndexLength);
                                if (part.IndexFormat == IndexFormat.TriangleStrip)
                                {
                                    indices = Unstrip(indices);
                                }

                                var faceCount = indices.Count() / 3;

                                bw.Write(mesh.MaterialIndex);
                                bw.Write(currentPosition);
                                bw.Write(faceCount);

                                currentPosition += faceCount;
                            }
                        }
                    }
                    #endregion

                    #region Shaders
                    headerValueList.Add(bw.BaseStream.Position);
                    foreach (var material in model.Materials)
                    {
                        const string nullPath = "null";

                        //skip null shaders
                        if (material == null)
                        {
                            bw.WriteStringNullTerminated(nullPath);
                            for (int i = 0; i < 8; i++)
                            {
                                bw.WriteStringNullTerminated(nullPath);
                            }

                            for (int i = 0; i < 4; i++)
                            {
                                bw.Write(0);
                            }

                            bw.Write(Convert.ToByte(false));
                            bw.Write(Convert.ToByte(false));

                            continue;
                        }

                        if (material.Flags.HasFlag(MaterialFlags.TerrainBlend))
                        {
                            bw.WriteStringNullTerminated("*" + material.Name);

                            var blendInfo  = material.Submaterials.FirstOrDefault(s => s.Usage == MaterialUsage.BlendMap);
                            var baseInfo   = material.Submaterials.Where(s => s.Usage == MaterialUsage.Diffuse).ToList();
                            var bumpInfo   = material.Submaterials.Where(s => s.Usage == MaterialUsage.Normal).ToList();
                            var detailInfo = material.Submaterials.Where(s => s.Usage == MaterialUsage.DiffuseDetail).ToList();

                            if (blendInfo == null)
                            {
                                bw.WriteStringNullTerminated(nullPath);
                            }
                            else
                            {
                                bw.WriteStringNullTerminated(blendInfo.Bitmap.Name);
                                bw.Write(blendInfo.Tiling.X);
                                bw.Write(blendInfo.Tiling.Y);
                            }

                            bw.Write((byte)baseInfo.Count);
                            bw.Write((byte)bumpInfo.Count);
                            bw.Write((byte)detailInfo.Count);

                            foreach (var info in baseInfo.Concat(bumpInfo).Concat(detailInfo))
                            {
                                bw.WriteStringNullTerminated(info.Bitmap.Name);
                                bw.Write(info.Tiling.X);
                                bw.Write(info.Tiling.Y);
                            }
                        }
                        else
                        {
                            bw.WriteStringNullTerminated(material.Name);
                            for (int i = 0; i < 8; i++)
                            {
                                var submat = material.Submaterials.FirstOrDefault(s => s.Usage == (MaterialUsage)i);
                                bw.WriteStringNullTerminated(submat?.Bitmap.Name ?? nullPath);
                                if (submat != null)
                                {
                                    bw.Write(submat.Tiling.X);
                                    bw.Write(submat.Tiling.Y);
                                }
                            }

                            for (int i = 0; i < 4; i++)
                            {
                                var tint = material.TintColours.FirstOrDefault(t => t.Usage == (TintUsage)i);
                                if (tint == null)
                                {
                                    bw.Write(0);
                                    continue;
                                }

                                bw.Write(tint.R);
                                bw.Write(tint.G);
                                bw.Write(tint.B);
                                bw.Write(tint.A);
                            }

                            bw.Write(Convert.ToByte(material.Flags.HasFlag(MaterialFlags.Transparent)));
                            bw.Write(Convert.ToByte(material.Flags.HasFlag(MaterialFlags.ColourChange)));
                        }
                    }
                    #endregion

                    #region Write Addresses
                    for (int i = 0; i < headerAddressList.Count; i++)
                    {
                        bw.BaseStream.Position = headerAddressList[i];
                        bw.Write((int)headerValueList[i]);
                    }

                    for (int i = 0; i < markerAddressList.Count; i++)
                    {
                        bw.BaseStream.Position = markerAddressList[i];
                        bw.Write((int)markerValueList[i]);
                    }

                    for (int i = 0; i < permAddressList.Count; i++)
                    {
                        bw.BaseStream.Position = permAddressList[i];
                        bw.Write((int)permValueList[i]);
                    }

                    for (int i = 0; i < vertAddressList.Count; i++)
                    {
                        bw.BaseStream.Position = vertAddressList[i];
                        bw.Write((int)vertValueList[i]);
                    }

                    for (int i = 0; i < indxAddressList.Count; i++)
                    {
                        bw.BaseStream.Position = indxAddressList[i];
                        bw.Write((int)indxValueList[i]);
                    }

                    for (int i = 0; i < meshAddressList.Count; i++)
                    {
                        bw.BaseStream.Position = meshAddressList[i];
                        bw.Write((int)meshValueList[i]);
                    }
                    #endregion
                }
        }