コード例 #1
0
ファイル: render_model.cs プロジェクト: Vegetal-Pole/Adjutant
        public IGeometryModel ReadGeometry(int lod)
        {
            if (lod < 0 || lod >= ((IRenderGeometry)this).LodCount)
            {
                throw new ArgumentOutOfRangeException(nameof(lod));
            }

            var model = new GeometryModel(item.FileName())
            {
                CoordinateSystem = CoordinateSystem.Default
            };

            model.Nodes.AddRange(Nodes);
            model.MarkerGroups.AddRange(MarkerGroups);
            model.Bounds.AddRange(BoundingBoxes);
            model.Materials.AddRange(Halo2.Halo2Common.GetMaterials(Shaders));

            foreach (var region in Regions)
            {
                var gRegion = new GeometryRegion {
                    SourceIndex = Regions.IndexOf(region), Name = region.Name
                };
                gRegion.Permutations.AddRange(region.Permutations.Select(p =>
                                                                         new GeometryPermutation
                {
                    SourceIndex = region.Permutations.IndexOf(p),
                    Name        = p.Name,
                    MeshIndex   = p.LodArray[lod],
                    MeshCount   = 1
                }));

                model.Regions.Add(gRegion);
            }

            foreach (var section in Sections)
            {
                var data        = section.DataPointer.ReadData(section.DataSize);
                var baseAddress = section.HeaderSize + 8;

                using (var ms = new MemoryStream(data))
                    using (var reader = new EndianReader(ms, ByteOrder.LittleEndian))
                    {
                        reader.ReadInt32(); //hklb
                        var sectionInfo = reader.ReadObject <MeshResourceDetailsBlock>();

                        var submeshResource = section.Resources[0];
                        var indexResource   = section.Resources.FirstOrDefault(r => r.Type0 == 48);
                        var vertexResource  = section.Resources.FirstOrDefault(r => r.Type0 == 92 && r.Type1 == 0);
                        var uvResource      = section.Resources.FirstOrDefault(r => r.Type0 == 92 && r.Type1 == 1);
                        var normalsResource = section.Resources.FirstOrDefault(r => r.Type0 == 92 && r.Type1 == 2);
                        var nodeMapResource = section.Resources.FirstOrDefault(r => r.Type0 == 164);

                        reader.Seek(baseAddress + submeshResource.Offset, SeekOrigin.Begin);
                        var submeshes = reader.ReadEnumerable <Halo2.SubmeshDataBlock>(submeshResource.Size / 72).ToList();

                        var mesh = new GeometryMesh {
                            BoundsIndex = 0,
                        };

                        foreach (var submesh in submeshes)
                        {
                            mesh.Submeshes.Add(new GeometrySubmesh
                            {
                                MaterialIndex = submesh.ShaderIndex,
                                IndexStart    = submesh.IndexStart,
                                IndexLength   = submesh.IndexLength
                            });
                        }

                        if (section.FaceCount * 3 == sectionInfo.IndexCount)
                        {
                            mesh.IndexFormat = IndexFormat.TriangleList;
                        }
                        else
                        {
                            mesh.IndexFormat = IndexFormat.TriangleStrip;
                        }

                        reader.Seek(baseAddress + indexResource.Offset, SeekOrigin.Begin);
                        mesh.Indicies = reader.ReadEnumerable <ushort>(sectionInfo.IndexCount).Select(i => (int)i).ToArray();

                        var nodeMap = new byte[0];
                        if (nodeMapResource != null)
                        {
                            reader.Seek(baseAddress + nodeMapResource.Offset, SeekOrigin.Begin);
                            nodeMap = reader.ReadBytes(sectionInfo.NodeMapCount);
                        }

                        #region Vertices
                        mesh.Vertices = new IVertex[section.VertexCount];
                        var vertexSize = vertexResource.Size / section.VertexCount;
                        for (int i = 0; i < section.VertexCount; i++)
                        {
                            var vert = new Halo2.Vertex();

                            reader.Seek(baseAddress + vertexResource.Offset + i * vertexSize, SeekOrigin.Begin);
                            vert.Position = new UInt16N4((ushort)(reader.ReadInt16() - short.MinValue), (ushort)(reader.ReadInt16() - short.MinValue), (ushort)(reader.ReadInt16() - short.MinValue), 0);
                            ReadBlendData(reader, section, mesh, vert, nodeMap);

                            mesh.Vertices[i] = vert;
                        }

                        for (int i = 0; i < section.VertexCount; i++)
                        {
                            var vert = (Halo2.Vertex)mesh.Vertices[i];

                            reader.Seek(baseAddress + uvResource.Offset + i * 4, SeekOrigin.Begin);
                            vert.TexCoords = new UInt16N2((ushort)(reader.ReadInt16() - short.MinValue), (ushort)(reader.ReadInt16() - short.MinValue));
                        }

                        for (int i = 0; i < section.VertexCount; i++)
                        {
                            var vert = (Halo2.Vertex)mesh.Vertices[i];

                            reader.Seek(baseAddress + normalsResource.Offset + i * 12, SeekOrigin.Begin);
                            vert.Normal = new HenDN3(reader.ReadUInt32());
                        }
                        #endregion

                        model.Meshes.Add(mesh);
                    }
            }

            return(model);
        }
コード例 #2
0
ファイル: render_model.cs プロジェクト: Vegetal-Pole/Adjutant
        private void ReadBlendData(EndianReader reader, SectionBlock section, GeometryMesh mesh, Halo2.Vertex vert, byte[] nodeMap)
        {
            if (section.NodesPerVertex == 0 && section.GeometryClassification == Halo2.GeometryClassification.Rigid)
            {
                mesh.NodeIndex = 0;
                return;
            }

            if (section.GeometryClassification == Halo2.GeometryClassification.Rigid)
            {
                mesh.VertexWeights = VertexWeights.Rigid;
            }
            else if (section.GeometryClassification == Halo2.GeometryClassification.RigidBoned)
            {
                mesh.VertexWeights = VertexWeights.Skinned;
                vert.BlendIndices  = new RealVector4D(reader.ReadByte(), 0, 0, 0);
                vert.BlendWeight   = new RealVector4D(1, 0, 0, 0);
                reader.ReadByte();
            }
            else if (section.GeometryClassification == Halo2.GeometryClassification.Skinned)
            {
                mesh.VertexWeights = VertexWeights.Skinned;
                if (section.NodesPerVertex == 2 || section.NodesPerVertex == 4)
                {
                    reader.ReadInt16();
                }

                var nodes   = Enumerable.Range(0, 4).Select(i => section.NodesPerVertex > i ? reader.ReadByte() : 0).ToList();
                var weights = Enumerable.Range(0, 4).Select(i => section.NodesPerVertex > i ? reader.ReadByte() / (float)byte.MaxValue : 0).ToList();

                if (section.NodesPerVertex == 1 && weights.Sum() == 0)
                {
                    weights[0] = 1;
                }

                vert.BlendIndices = new RealVector4D(nodes[0], nodes[1], nodes[2], nodes[3]);
                vert.BlendWeight  = new RealVector4D(weights[0], weights[1], weights[2], weights[3]);
            }

            if (nodeMap.Length > 0)
            {
                var temp = vert.BlendIndices;
                vert.BlendIndices = new RealVector4D
                {
                    X = section.NodesPerVertex > 0 ? nodeMap[(int)temp.X] : 0,
                    Y = section.NodesPerVertex > 1 ? nodeMap[(int)temp.Y] : 0,
                    Z = section.NodesPerVertex > 2 ? nodeMap[(int)temp.Z] : 0,
                    W = section.NodesPerVertex > 3 ? nodeMap[(int)temp.W] : 0,
                };
            }
        }