Exemplo n.º 1
0
        private SsbhVertexAttribute[] ReadAttributeVec4(MeshAttribute attr, int position, int count, BinaryReader buffer, int offset, int stride)
        {
            var format     = (MeshAttribute.AttributeDataType)attr.DataType;
            var attributes = new SsbhVertexAttribute[count];

            for (int i = 0; i < count; i++)
            {
                buffer.BaseStream.Position = offset + attr.BufferOffset + stride * (position + i);

                switch (format)
                {
                // TODO: Add option to not convert smaller types to larger types.
                case MeshAttribute.AttributeDataType.Byte:
                    attributes[i] = new SsbhVertexAttribute(buffer.ReadByte(), buffer.ReadByte(), buffer.ReadByte(), buffer.ReadByte());
                    break;

                case MeshAttribute.AttributeDataType.Float:
                    attributes[i] = new SsbhVertexAttribute(buffer.ReadSingle(), buffer.ReadSingle(), buffer.ReadSingle(), buffer.ReadSingle());
                    break;

                case MeshAttribute.AttributeDataType.HalfFloat:
                    attributes[i] = new SsbhVertexAttribute(ReadHalfFloat(buffer), ReadHalfFloat(buffer), ReadHalfFloat(buffer), ReadHalfFloat(buffer));
                    break;

                case MeshAttribute.AttributeDataType.HalfFloat2:
                    attributes[i] = new SsbhVertexAttribute(ReadHalfFloat(buffer), ReadHalfFloat(buffer), ReadHalfFloat(buffer), ReadHalfFloat(buffer));
                    break;
                }
            }

            return(attributes);
        }
Exemplo n.º 2
0
        private SsbhVertexAttribute[] ReadAttributeVec4(MeshAttribute attr, int position, int count, string attributeName, BinaryReader buffer, int offset, int stride)
        {
            var format     = (SsbVertexAttribFormat)attr.DataType;
            var attributes = new SsbhVertexAttribute[count];

            for (int i = 0; i < count; i++)
            {
                buffer.BaseStream.Position = offset + attr.BufferOffset + stride * (position + i);

                switch (format)
                {
                case SsbVertexAttribFormat.Byte:
                    attributes[i] = new SsbhVertexAttribute(buffer.ReadByte(), buffer.ReadByte(), buffer.ReadByte(), buffer.ReadByte());
                    break;

                case SsbVertexAttribFormat.Float:
                    attributes[i] = new SsbhVertexAttribute(buffer.ReadSingle(), buffer.ReadSingle(), buffer.ReadSingle(), buffer.ReadSingle());
                    break;

                case SsbVertexAttribFormat.HalfFloat:
                    attributes[i] = new SsbhVertexAttribute(ReadHalfFloat(buffer), ReadHalfFloat(buffer), ReadHalfFloat(buffer), ReadHalfFloat(buffer));
                    break;

                case SsbVertexAttribFormat.HalfFloat2:
                    attributes[i] = new SsbhVertexAttribute(ReadHalfFloat(buffer), ReadHalfFloat(buffer), ReadHalfFloat(buffer), ReadHalfFloat(buffer));
                    break;
                }
            }

            return(attributes);
        }
Exemplo n.º 3
0
        private SsbhVertexAttribute[] ReadAttribute(MeshAttribute attr, int count, MeshObject meshObject)
        {
            if (attr == null)
            {
                return(new SsbhVertexAttribute[0]);
            }

            string attributeName = attr.AttributeStrings[0].Text;

            // TODO: There are optimizations possible for reading if the data is tighly packed.
            // The stride may not allow this.
            int offset = meshObject.VertexOffset;
            int stride = meshObject.Stride;

            if (attr.BufferIndex == 1)
            {
                offset = meshObject.VertexOffset2;
                stride = meshObject.Stride2;
            }

            SsbhVertexAttribute[] attributes = null;
            int attributeLength = GetAttributeComponentCount(attributeName);

            using (BinaryReader attributeBuffer = new BinaryReader(new MemoryStream(meshFile.VertexBuffers[attr.BufferIndex].Buffer)))
            {
                attributes = ReadAttribute(attr, count, attributeBuffer, offset, stride, attributeLength);
            }

            return(attributes);
        }
Exemplo n.º 4
0
        public void LoadRawAsset()
        {
            if (this.RawRes != null || !File.Exists(this.AssetPath))
            {
                return;
            }

            switch (this.ResourceType)
            {
            case EResoucresTypes.TextureType:
                RawRes = new TextureAttribute(this);
                break;

            case EResoucresTypes.MatrialType:
                RawRes = new MaterialAttribute(this);
                break;

            case EResoucresTypes.ShaderType:
                RawRes = new ShaderAttribute(this);
                break;

            case EResoucresTypes.MeshType:
                RawRes = new MeshAttribute(this);
                break;
            }
        }
Exemplo n.º 5
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="attr"></param>
        /// <param name="position"></param>
        /// <param name="count"></param>
        /// <param name="meshObject"></param>
        /// <returns></returns>
        private SsbhVertexAttribute[] ReadAttribute(MeshAttribute attr, int position, int count, MeshObject meshObject)
        {
            if (attr == null)
            {
                return(new SsbhVertexAttribute[0]);
            }

            string attributeName = attr.AttributeStrings[0].Name;

            var buffers = new BinaryReader[meshFile.VertexBuffers.Length];

            for (int i = 0; i < meshFile.VertexBuffers.Length; i++)
            {
                buffers[i] = new BinaryReader(new MemoryStream(meshFile.VertexBuffers[i].Buffer));
            }

            BinaryReader selectedBuffer = buffers[attr.BufferIndex];

            int offset = meshObject.VertexOffset;
            int stride = meshObject.Stride;

            if (attr.BufferIndex == 1)
            {
                offset = meshObject.VertexOffset2;
                stride = meshObject.Stride2;
            }

            SsbhVertexAttribute[] attributes = null;
            int attributeLength = GetAttributeLength(attributeName);

            switch (attributeLength)
            {
            case 1:
                attributes = ReadAttributeScalar(attr, position, count, attributeName, selectedBuffer, offset, stride);
                break;

            case 2:
                attributes = ReadAttributeVec2(attr, position, count, attributeName, selectedBuffer, offset, stride);
                break;

            case 3:
                attributes = ReadAttributeVec3(attr, position, count, attributeName, selectedBuffer, offset, stride);
                break;

            case 4:
                attributes = ReadAttributeVec4(attr, position, count, attributeName, selectedBuffer, offset, stride);
                break;
            }

            foreach (var buffer in buffers)
            {
                buffer.Close();
                buffer.Dispose();
            }

            return(attributes);
        }
Exemplo n.º 6
0
        public SSBHVertexAttribute[] ReadAttribute(string AttributeName, int Position, int Count, MeshObject MeshObject)
        {
            MeshAttribute attr = GetAttribute(AttributeName, MeshObject);

            if (attr == null)
            {
                return(new SSBHVertexAttribute[0]);
            }
            BinaryReader SelectedBuffer = buffers[attr.BufferIndex];

            int Offset = MeshObject.VertexOffset;
            int Stride = MeshObject.Stride;

            if (attr.BufferIndex == 1)
            {
                Offset = MeshObject.VertexOffset2;
                Stride = MeshObject.Stride2;
            }

            int Size = 3;

            if (AttributeName.Contains("colorSet"))
            {
                Size = 4;
            }
            if (AttributeName.Equals("map1") || AttributeName.Equals("bake1") || AttributeName.Contains("uvSet"))
            {
                Size = 2;
            }

            SSBHVertexAttribute[] a = new SSBHVertexAttribute[Count];
            for (int i = 0; i < Count; i++)
            {
                SelectedBuffer.BaseStream.Position = Offset + attr.BufferOffset + Stride * (Position + i);
                a[i] = new SSBHVertexAttribute();

                if (Size > 0)
                {
                    a[i].X = ReadAttribute(SelectedBuffer, (SSBVertexAttribFormat)attr.DataType);
                }
                if (Size > 1)
                {
                    a[i].Y = ReadAttribute(SelectedBuffer, (SSBVertexAttribFormat)attr.DataType);
                }
                if (Size > 2)
                {
                    a[i].Z = ReadAttribute(SelectedBuffer, (SSBVertexAttribFormat)attr.DataType);
                }
                if (Size > 3)
                {
                    a[i].W = ReadAttribute(SelectedBuffer, (SSBVertexAttribFormat)attr.DataType);
                }
            }

            return(a);
        }
Exemplo n.º 7
0
        /// <summary>
        /// Sets a vertex attribute array for the given <paramref name="bindingID"/>.
        /// </summary>
        /// <param name="bindingID">The binding ID.</param>
        /// <param name="data">The attribute array data.</param>
        /// <param name="perInstance">
        /// if set to <c>true</c> attribute array contains one entry for each instance
        /// if set to <c>false</c> all attribute array elements are for one instance
        /// </param>
        public void SetAttribute <ELEMENT_TYPE>(int bindingID, ELEMENT_TYPE[] data, bool perInstance = false) where ELEMENT_TYPE : struct
        {
            var type          = typeof(ELEMENT_TYPE);
            var baseTypeCount = MeshAttribute.GetBaseTypeCount(type);

            if (baseTypeCount > 1)
            {
                type = typeof(float);
            }
            SetAttribute(bindingID, data, type, baseTypeCount, perInstance);
        }
Exemplo n.º 8
0
        public VAO GetDrawable(DefaultMesh mesh, DrawableType type)
        {
            MeshAttribute uvs = mesh.GetAttribute("uv");

            int elems = uvs.ToArray().Length;

            if (elems == 0)
            {
                mesh.SetConstantUV(new Vector2(0, 0));
            }
            IShaderProgram shader = GetShader(type);
            VAO            res    = VAOLoader.FromMesh(mesh, shader);

            return(res);
        }
Exemplo n.º 9
0
        private SsbhVertexAttribute[] ReadAttribute(MeshAttribute attr, int count, BinaryReader buffer, int offset, int stride, int attributeLength)
        {
            var format     = attr.DataType;
            var attributes = new SsbhVertexAttribute[count];

            for (int i = 0; i < count; i++)
            {
                buffer.BaseStream.Position = offset + attr.BufferOffset + stride * i;

                attributes[i] = new SsbhVertexAttribute();

                switch (format)
                {
                // TODO: Add option to not convert smaller types to larger types.
                case MeshAttribute.AttributeDataType.Byte:
                    for (int j = 0; j < attributeLength; j++)
                    {
                        attributes[i][j] = buffer.ReadByte();
                    }
                    break;

                case MeshAttribute.AttributeDataType.Float:
                    for (int j = 0; j < attributeLength; j++)
                    {
                        attributes[i][j] = buffer.ReadSingle();
                    }
                    break;

                case MeshAttribute.AttributeDataType.HalfFloat:
                    for (int j = 0; j < attributeLength; j++)
                    {
                        attributes[i][j] = ReadHalfFloat(buffer);
                    }
                    break;

                case MeshAttribute.AttributeDataType.HalfFloat2:
                    for (int j = 0; j < attributeLength; j++)
                    {
                        attributes[i][j] = ReadHalfFloat(buffer);
                    }
                    break;
                }
            }

            return(attributes);
        }
Exemplo n.º 10
0
        private static VertexAttribPointerType GetAttributeType(MeshAttribute meshAttribute)
        {
            switch (meshAttribute.DataType)
            {
            case 0:
                return(VertexAttribPointerType.Float);

            case 2:
                return(VertexAttribPointerType.Byte);    // color

            case 5:
                return(VertexAttribPointerType.HalfFloat);

            case 8:
                return(VertexAttribPointerType.HalfFloat);

            default:
                return(VertexAttribPointerType.Float);
            }
        }
Exemplo n.º 11
0
        private static int TryParseAttrib(string line, ref MeshAttribute attrib)
        {
            if (line.StartsWith("VERTICES"))
            {
                attrib = MeshAttribute.Position;
            }
            else if (line.StartsWith("VERTEXNORMALS"))
            {
                attrib = MeshAttribute.Normal;
            }
            else if (line.StartsWith("POLYGONS"))
            {
                attrib = MeshAttribute.Polygon;
            }
            else if (line.StartsWith("WEIGHT"))
            {
                attrib = MeshAttribute.Weight;
            }
            else if (line.StartsWith("MORPH"))
            {
                attrib = MeshAttribute.Morph;
            }
            else if (line.StartsWith("UV"))
            {
                attrib = MeshAttribute.Uv;
            }
            else
            {
                return(-1);
            }

            string[] split = line.Split(':');

            int size = 0;

            int.TryParse(split[split.Length - 1], out size);

            return(size);
        }
Exemplo n.º 12
0
        /// <summary>
        /// Import from ODVertexData file.
        /// </summary>
        /// <param name="path"></param>
        /// <param name="mesh"></param>
        /// <param name="materials"></param>
        /// <returns></returns>
        public static bool Import(string path, out Mesh mesh, out string[] materials)
        {
            MeshAttribute  attrib    = MeshAttribute.Null;
            List <Vector3> positions = new List <Vector3>();
            List <Vector3> normals   = new List <Vector3>();
            List <Polygon> polygons  = new List <Polygon>();
            List <UVCoord> uvs       = new List <UVCoord>();

            using (StreamReader reader = new StreamReader(path))
            {
                for (string line = reader.ReadLine(); line != null; line = reader.ReadLine())
                {
                    int attributeCount = TryParseAttrib(line, ref attrib);

                    if (attributeCount > -1)
                    {
                        continue;
                    }

                    if (attrib == MeshAttribute.Position)
                    {
                        TryParseVector3(line, positions);
                    }
                    else if (attrib == MeshAttribute.Normal)
                    {
                        TryParseVector3(line, normals);
                    }
                    else if (attrib == MeshAttribute.Uv)
                    {
                        TryParseUv(line, uvs);
                    }
                    else if (attrib == MeshAttribute.Polygon)
                    {
                        TryParsePolygon(line, polygons);
                    }
                }
            }

            bool hasNormals = normals.Count == positions.Count;

            if (PasteConvertsHandedness)
            {
                for (int i = 0; i < positions.Count; i++)
                {
                    // todo More options for swapping coordinate systems around (eg, max w/ z up)
                    positions[i] = new Vector3(-positions[i].x, positions[i].y, positions[i].z);

                    if (hasNormals)
                    {
                        normals[i] = new Vector3(-normals[i].x, normals[i].y, normals[i].z);
                    }
                }
            }

            materials = new string[0];
            mesh      = null;

            List <Vertex> vertices;
            Dictionary <string, List <int> > indices;

            if (!MeshUtility.GeneratePerTriangleVertices(positions,
                                                         normals,
                                                         uvs,
                                                         polygons,
                                                         out vertices,
                                                         out indices))
            {
                return(false);
            }

            materials = indices.Select(x => x.Key).ToArray();
            mesh      = MeshUtility.CompileMesh(vertices, indices, !SplitVertices);
            mesh.name = "ODCopyPaste_Mesh";
            mesh.RecalculateNormals();
            mesh.RecalculateTangents();
            mesh.RecalculateBounds();

            return(true);
        }
Exemplo n.º 13
0
        /// <summary>
        /// Reads the attribute data from the mesh object with the given name
        /// </summary>
        /// <param name="attributeName"></param>
        /// <param name="position"></param>
        /// <param name="count"></param>
        /// <param name="meshObject"></param>
        /// <returns>null if attribute name not found</returns>
        public SsbhVertexAttribute[] ReadAttribute(string attributeName, int position, int count, MeshObject meshObject)
        {
            MeshAttribute attr = GetAttribute(attributeName, meshObject);

            return(ReadAttribute(attr, position, count, meshObject));
        }
Exemplo n.º 14
0
 /// <summary>
 /// Reads the vertex attribute information for the given attribute name inside of the mesh object.
 /// </summary>
 /// <param name="attributeName"></param>
 /// <param name="meshObject"></param>
 /// <returns>null if attribute name not found</returns>
 public SsbhVertexAttribute[] ReadAttribute(MeshAttribute attributeName, MeshObject meshObject)
 {
     return(ReadAttribute(attributeName, 0, meshObject.VertexCount, meshObject));
 }
Exemplo n.º 15
0
        /// <summary>
        /// Creates and returns a mesh file
        /// </summary>
        /// <returns></returns>
        public Mesh GetMeshFile()
        {
            Mesh mesh = new Mesh
            {
                //TODO: bounding box stuff
                // Rigging
                Objects = new MeshObject[meshes.Count]
            };

            // create mesh objects and buffers
            BinaryWriter             vertexBuffer1     = new BinaryWriter(new MemoryStream());
            BinaryWriter             vertexBuffer2     = new BinaryWriter(new MemoryStream()); // there are actually 4 buffers, but only 2 seem to be used
            BinaryWriter             indexBuffer       = new BinaryWriter(new MemoryStream());
            int                      finalBufferOffset = 0;
            int                      meshIndex         = 0;
            Dictionary <string, int> meshGroups        = new Dictionary <string, int>();
            List <MeshRiggingGroup>  riggingGroups     = new List <MeshRiggingGroup>();

            foreach (var tempmesh in meshes)
            {
                MeshObject mo = new MeshObject
                {
                    Name = tempmesh.Name
                };
                if (meshGroups.ContainsKey(mo.Name))
                {
                    meshGroups[mo.Name] += 1;
                }
                else
                {
                    meshGroups.Add(mo.Name, 0);
                }

                mo.SubIndex             = meshGroups[mo.Name];
                mo.BoundingSphereCenter = new Formats.Vector3 {
                    X = tempmesh.BoundingSphere.X, Y = tempmesh.BoundingSphere.Y, Z = tempmesh.BoundingSphere.Z
                };
                mo.BoundingSphereRadius = tempmesh.BoundingSphere.W;

                mo.BoundingBoxMax = new Formats.Vector3 {
                    X = tempmesh.BbMax.X, Y = tempmesh.BbMax.Y, Z = tempmesh.BbMax.Z
                };
                mo.BoundingBoxMin = new Formats.Vector3 {
                    X = tempmesh.BbMin.X, Y = tempmesh.BbMin.Y, Z = tempmesh.BbMin.Z
                };
                mo.OrientedBoundingBoxCenter = new Formats.Vector3 {
                    X = tempmesh.ObbCenter.X, Y = tempmesh.ObbCenter.Y, Z = tempmesh.ObbCenter.Z
                };

                mo.OrientedBoundingBoxSize = new Formats.Vector3 {
                    X = tempmesh.ObbSize.X, Y = tempmesh.ObbSize.Y, Z = tempmesh.ObbSize.Z
                };

                mo.OrientedBoundingBoxTransform.Row1.X = tempmesh.ObbMatrix3X3[0];
                mo.OrientedBoundingBoxTransform.Row1.Y = tempmesh.ObbMatrix3X3[1];
                mo.OrientedBoundingBoxTransform.Row1.Z = tempmesh.ObbMatrix3X3[2];
                mo.OrientedBoundingBoxTransform.Row2.X = tempmesh.ObbMatrix3X3[3];
                mo.OrientedBoundingBoxTransform.Row2.Y = tempmesh.ObbMatrix3X3[4];
                mo.OrientedBoundingBoxTransform.Row2.Z = tempmesh.ObbMatrix3X3[5];
                mo.OrientedBoundingBoxTransform.Row3.X = tempmesh.ObbMatrix3X3[6];
                mo.OrientedBoundingBoxTransform.Row3.Y = tempmesh.ObbMatrix3X3[7];
                mo.OrientedBoundingBoxTransform.Row3.Z = tempmesh.ObbMatrix3X3[8];


                // Create Rigging
                riggingGroups.Add(SsbhRiggingCompiler.CreateRiggingGroup(mo.Name, (int)mo.SubIndex, tempmesh.Influences.ToArray()));

                // set object
                mesh.Objects[meshIndex++] = mo;

                mo.ParentBoneName = tempmesh.ParentBone;
                if (tempmesh.Influences.Count > 0 && (tempmesh.ParentBone == null || tempmesh.ParentBone.Equals("")))
                {
                    mo.RiggingType = RiggingType.Regular;
                }

                int stride1 = 0;
                int stride2 = 0;

                mo.VertexOffset  = (int)vertexBuffer1.BaseStream.Length;
                mo.VertexOffset2 = (int)vertexBuffer2.BaseStream.Length;
                mo.ElementOffset = (uint)indexBuffer.BaseStream.Length;

                // gather strides
                mo.Attributes = new MeshAttribute[tempmesh.VertexData.Count];
                int attributeIndex = 0;
                foreach (var keypair in tempmesh.VertexData)
                {
                    // For some reason the attribute string doesn't match the attribute's name for Tangent0.
                    var attributeName = keypair.Key.Name;
                    if (keypair.Key.Name == "Tangent0")
                    {
                        attributeName = "map1";
                    }

                    MeshAttribute attr = new MeshAttribute
                    {
                        Name             = attributeName,
                        Index            = keypair.Key.Index,
                        BufferIndex      = keypair.Key.BufferIndex,
                        DataType         = keypair.Key.DataType,
                        BufferOffset     = keypair.Key.BufferIndex == 0 ? stride1 : stride2,
                        AttributeStrings = new MeshAttributeString[] { new MeshAttributeString()
                                                                       {
                                                                           Name = keypair.Key.Name
                                                                       } }
                    };
                    mo.Attributes[attributeIndex++] = attr;

                    if (keypair.Key.BufferIndex == 0)
                    {
                        stride1 += keypair.Key.ComponentCount * keypair.Key.DataType.GetSizeInBytes();
                    }
                    else
                    {
                        stride2 += keypair.Key.ComponentCount * keypair.Key.DataType.GetSizeInBytes();
                    }
                }

                // now that strides are known...
                long buffer1Start = vertexBuffer1.BaseStream.Length;
                long buffer2Start = vertexBuffer2.BaseStream.Length;
                vertexBuffer1.Write(new byte[stride1 * tempmesh.VertexCount]);
                vertexBuffer2.Write(new byte[stride2 * tempmesh.VertexCount]);
                attributeIndex = 0;
                foreach (var keypair in tempmesh.VertexData)
                {
                    var     attr           = mo.Attributes[attributeIndex++];
                    float[] data           = keypair.Value;
                    var     buffer         = attr.BufferIndex == 0 ? vertexBuffer1 : vertexBuffer2;
                    int     bufferOffset   = (int)(attr.BufferIndex == 0 ? buffer1Start : buffer2Start);
                    int     stride         = (attr.BufferIndex == 0 ? stride1 : stride2);
                    int     componentCount = keypair.Key.ComponentCount;
                    for (int vertexIndex = 0; vertexIndex < tempmesh.VertexCount; vertexIndex++)
                    {
                        buffer.Seek(bufferOffset + stride * vertexIndex + attr.BufferOffset, SeekOrigin.Begin);
                        for (int j = 0; j < componentCount; j++)
                        {
                            WriteType(buffer, attr.DataType, data[vertexIndex * componentCount + j]);
                        }
                    }
                    // seek to end just to make sure
                    buffer.Seek((int)buffer.BaseStream.Length, SeekOrigin.Begin);
                }

                mo.FinalBufferOffset = finalBufferOffset;
                finalBufferOffset   += (4 + stride1) * tempmesh.VertexCount;
                mo.VertexCount       = tempmesh.VertexCount;
                mo.IndexCount        = tempmesh.Indices.Count;
                mo.Stride            = stride1;
                mo.Stride2           = stride2;

                // write index buffer
                if (tempmesh.VertexCount > ushort.MaxValue)
                {
                    mo.DrawElementType = DrawElementType.UnsignedInt;
                    foreach (var i in tempmesh.Indices)
                    {
                        indexBuffer.Write(i);
                    }
                }
                else
                {
                    foreach (var i in tempmesh.Indices)
                    {
                        indexBuffer.Write((ushort)i);
                    }
                }
            }

            mesh.PolygonIndexSize = indexBuffer.BaseStream.Length;
            mesh.BufferSizes      = new int[] { (int)vertexBuffer1.BaseStream.Length, (int)vertexBuffer2.BaseStream.Length, 0, 0 };
            mesh.PolygonBuffer    = ((MemoryStream)indexBuffer.BaseStream).ToArray();
            Console.WriteLine(mesh.PolygonBuffer.Length + " " + indexBuffer.BaseStream.Length);
            mesh.VertexBuffers = new MeshBuffer[]
            {
                new MeshBuffer {
                    Buffer = ((MemoryStream)vertexBuffer1.BaseStream).ToArray()
                },
                new MeshBuffer {
                    Buffer = ((MemoryStream)vertexBuffer2.BaseStream).ToArray()
                },
                new MeshBuffer {
                    Buffer = new byte[0]
                },
                new MeshBuffer {
                    Buffer = new byte[0]
                }
            };

            mesh.RiggingBuffers = riggingGroups.ToArray().OrderBy(o => o.MeshName, StringComparer.Ordinal).ToArray();

            vertexBuffer1.Close();
            vertexBuffer2.Close();
            indexBuffer.Close();

            return(mesh);
        }
Exemplo n.º 16
0
        /// <summary>
        /// Creates and returns a mesh file
        /// </summary>
        /// <returns></returns>
        public MESH GetMeshFile()
        {
            MESH mesh = new MESH
            {
                //TODO: bounding box stuff
                // Rigging
                Objects = new MeshObject[meshes.Count]
            };

            // create mesh objects and buffers
            BinaryWriter             vertexBuffer1     = new BinaryWriter(new MemoryStream());
            BinaryWriter             vertexBuffer2     = new BinaryWriter(new MemoryStream()); // there are actually 4 buffers, but only 2 seem to be used
            BinaryWriter             indexBuffer       = new BinaryWriter(new MemoryStream());
            int                      finalBufferOffset = 0;
            int                      meshIndex         = 0;
            Dictionary <string, int> MeshGroups        = new Dictionary <string, int>();
            List <MeshRiggingGroup>  RiggingGroups     = new List <MeshRiggingGroup>();

            foreach (var tempmesh in meshes)
            {
                MeshObject mo = new MeshObject
                {
                    Name = tempmesh.Name
                };
                if (MeshGroups.ContainsKey(mo.Name))
                {
                    MeshGroups[mo.Name] += 1;
                }
                else
                {
                    MeshGroups.Add(mo.Name, 0);
                }

                mo.SubMeshIndex         = MeshGroups[mo.Name];
                mo.BoundingSphereX      = tempmesh.BoundingSphere.X;
                mo.BoundingSphereY      = tempmesh.BoundingSphere.Y;
                mo.BoundingSphereZ      = tempmesh.BoundingSphere.Z;
                mo.BoundingSphereRadius = tempmesh.BoundingSphere.W;

                mo.MaxBoundingBoxX = tempmesh.BBMax.X;
                mo.MaxBoundingBoxY = tempmesh.BBMax.Y;
                mo.MaxBoundingBoxZ = tempmesh.BBMax.Z;
                mo.MinBoundingBoxX = tempmesh.BBMin.X;
                mo.MinBoundingBoxY = tempmesh.BBMin.Y;
                mo.MinBoundingBoxZ = tempmesh.BBMin.Z;

                mo.OBBCenterX = tempmesh.OBBCenter.X;
                mo.OBBCenterY = tempmesh.OBBCenter.Y;
                mo.OBBCenterZ = tempmesh.OBBCenter.Z;

                mo.OBBSizeX = tempmesh.OBBSize.X;
                mo.OBBSizeY = tempmesh.OBBSize.Y;
                mo.OBBSizeZ = tempmesh.OBBSize.Z;

                mo.M11 = tempmesh.OBBMatrix3x3[0];
                mo.M12 = tempmesh.OBBMatrix3x3[1];
                mo.M13 = tempmesh.OBBMatrix3x3[2];
                mo.M21 = tempmesh.OBBMatrix3x3[3];
                mo.M22 = tempmesh.OBBMatrix3x3[4];
                mo.M23 = tempmesh.OBBMatrix3x3[5];
                mo.M31 = tempmesh.OBBMatrix3x3[6];
                mo.M32 = tempmesh.OBBMatrix3x3[7];
                mo.M33 = tempmesh.OBBMatrix3x3[8];


                // Create Rigging
                RiggingGroups.Add(SSBHRiggingCompiler.CreateRiggingGroup(mo.Name, (int)mo.SubMeshIndex, tempmesh.Influences.ToArray()));

                // set object
                mesh.Objects[meshIndex++] = mo;

                mo.ParentBoneName = tempmesh.ParentBone;
                if (tempmesh.Influences.Count > 0 && (tempmesh.ParentBone == null || tempmesh.ParentBone.Equals("")))
                {
                    mo.HasRigging = 1;
                }

                int Stride1 = 0;
                int Stride2 = 0;

                mo.VertexOffset  = (int)vertexBuffer1.BaseStream.Length;
                mo.VertexOffset2 = (int)vertexBuffer2.BaseStream.Length;
                mo.ElementOffset = (uint)indexBuffer.BaseStream.Length;

                // gather strides
                mo.Attributes = new MeshAttribute[tempmesh.VertexData.Count];
                int attributeIndex = 0;
                foreach (var keypair in tempmesh.VertexData)
                {
                    MeshAttribute attr = new MeshAttribute
                    {
                        Name             = GetAttributeName(keypair.Key),
                        Index            = GetAttributeIndex(keypair.Key),
                        BufferIndex      = GetBufferIndex(keypair.Key),
                        DataType         = GetAttributeDataType(keypair.Key),
                        BufferOffset     = (GetBufferIndex(keypair.Key) == 0) ? Stride1 : Stride2,
                        AttributeStrings = new MeshAttributeString[] { new MeshAttributeString()
                                                                       {
                                                                           Name = keypair.Key.ToString()
                                                                       } }
                    };
                    mo.Attributes[attributeIndex++] = attr;

                    if (GetBufferIndex(keypair.Key) == 0)
                    {
                        Stride1 += GetAttributeSize(keypair.Key) * GetAttributeDataSize(keypair.Key);
                    }
                    else
                    {
                        Stride2 += GetAttributeSize(keypair.Key) * GetAttributeDataSize(keypair.Key);
                    }
                }

                // now that strides are known...
                long Buffer1Start = vertexBuffer1.BaseStream.Length;
                long Buffer2Start = vertexBuffer2.BaseStream.Length;
                vertexBuffer1.Write(new byte[Stride1 * tempmesh.VertexCount]);
                vertexBuffer2.Write(new byte[Stride2 * tempmesh.VertexCount]);
                attributeIndex = 0;
                foreach (var keypair in tempmesh.VertexData)
                {
                    var     attr         = mo.Attributes[attributeIndex++];
                    float[] Data         = keypair.Value;
                    var     buffer       = attr.BufferIndex == 0 ? vertexBuffer1 : vertexBuffer2;
                    int     bufferOffset = (int)(attr.BufferIndex == 0 ? Buffer1Start : Buffer2Start);
                    int     stride       = (attr.BufferIndex == 0 ? Stride1 : Stride2);
                    int     size         = GetAttributeSize(keypair.Key);
                    for (int vertexIndex = 0; vertexIndex < tempmesh.VertexCount; vertexIndex++)
                    {
                        buffer.Seek(bufferOffset + stride * vertexIndex + attr.BufferOffset, SeekOrigin.Begin);
                        for (int j = 0; j < size; j++)
                        {
                            WriteType(buffer, attr.DataType, Data[vertexIndex * size + j]);
                        }
                    }
                    // seek to end just to make sure
                    buffer.Seek((int)buffer.BaseStream.Length, SeekOrigin.Begin);
                }

                mo.FinalBufferOffset = finalBufferOffset;
                finalBufferOffset   += (4 + Stride1) * tempmesh.VertexCount;
                mo.VertexCount       = tempmesh.VertexCount;
                mo.IndexCount        = tempmesh.Indices.Count;
                mo.Stride            = Stride1;
                mo.Stride2           = Stride2;

                // write index buffer
                if (tempmesh.VertexCount > ushort.MaxValue)
                {
                    mo.DrawElementType = 1;
                    foreach (var i in tempmesh.Indices)
                    {
                        indexBuffer.Write(i);
                    }
                }
                else
                {
                    foreach (var i in tempmesh.Indices)
                    {
                        indexBuffer.Write((ushort)i);
                    }
                }
            }

            mesh.PolygonIndexSize = indexBuffer.BaseStream.Length;
            mesh.BufferSizes      = new int[] { (int)vertexBuffer1.BaseStream.Length, (int)vertexBuffer2.BaseStream.Length, 0, 0 };
            mesh.PolygonBuffer    = ((MemoryStream)indexBuffer.BaseStream).ToArray();
            Console.WriteLine(mesh.PolygonBuffer.Length + " " + indexBuffer.BaseStream.Length);
            mesh.VertexBuffers = new MeshBuffer[]
            {
                new MeshBuffer()
                {
                    Buffer = ((MemoryStream)vertexBuffer1.BaseStream).ToArray()
                },
                new MeshBuffer()
                {
                    Buffer = ((MemoryStream)vertexBuffer2.BaseStream).ToArray()
                },
                new MeshBuffer()
                {
                    Buffer = new byte[0]
                },
                new MeshBuffer()
                {
                    Buffer = new byte[0]
                }
            };

            mesh.RiggingBuffers = RiggingGroups.ToArray().OrderBy(o => o.Name, StringComparer.Ordinal).ToArray();

            vertexBuffer1.Close();
            vertexBuffer2.Close();
            indexBuffer.Close();

            return(mesh);
        }