Ejemplo n.º 1
0
        public Shape()
        {
            MatrixGroups = new List <MatrixGroup>();

            VertexDescription = new VertexDescription();
            ShapeMaterial     = null;

            VertexData = new MeshVertexHolder();
            Indices    = new List <int>();
        }
Ejemplo n.º 2
0
            public Shape()
            {
                Attributes        = new List <ShapeVertexAttribute>();
                VertexData        = new MeshVertexHolder();
                Indexes           = new List <int>();
                VertexDescription = new VertexDescription();
                MatrixDataTable   = new List <SkinDataTable>();
                OverrideVertPos   = new List <Vector3>();
                OverrideNormals   = new List <Vector3>();

                m_glBufferIndexes = new int[15];
                for (int i = 0; i < m_glBufferIndexes.Length; i++)
                {
                    m_glBufferIndexes[i] = -1;
                }

                m_glIndexBuffer = GL.GenBuffer();
            }
Ejemplo n.º 3
0
        public void ReadSHP1FromStream(EndianBinaryReader reader, long tagStart, MeshVertexHolder compressedVertexData)
        {
            ShapeCount = reader.ReadInt16();
            Trace.Assert(reader.ReadUInt16() == 0xFFFF); // Padding
            int shapeOffset = reader.ReadInt32();

            // Another index remap table.
            int remapTableOffset = reader.ReadInt32();

            Trace.Assert(reader.ReadInt32() == 0);
            int attributeOffset = reader.ReadInt32();

            // Offset to the Matrix Table which holds a list of ushorts used for ??
            int matrixTableOffset = reader.ReadInt32();

            // Offset to the array of primitive's data.
            int primitiveDataOffset  = reader.ReadInt32();
            int matrixDataOffset     = reader.ReadInt32();
            int packetLocationOffset = reader.ReadInt32();

            reader.BaseStream.Position = tagStart + remapTableOffset;
            ShapeRemapTable            = new List <short>();
            for (int i = 0; i < ShapeCount; i++)
            {
                ShapeRemapTable.Add(reader.ReadInt16());
            }

            for (int s = 0; s < ShapeCount; s++)
            {
                // Shapes can have different attributes for each shape. (ie: Some have only Position, while others have Pos & TexCoord, etc.) Each
                // shape (which has a consistent number of attributes) it is split into individual packets, which are a collection of geometric primitives.
                // Each packet can have individual unique skinning data.

                reader.BaseStream.Position = tagStart + shapeOffset + (0x28 * s) /* 0x28 is the size of one Shape entry*/;
                long  shapeStart = reader.BaseStream.Position;
                Shape shape      = new Shape();
                shape.MatrixType = reader.ReadByte();
                Trace.Assert(reader.ReadByte() == 0xFF); // Padding

                // Number of Packets (of data) contained in this Shape
                ushort packetCount = reader.ReadUInt16();

                // Offset from the start of the Attribute List to the attributes this particular batch uses.
                ushort batchAttributeOffset = reader.ReadUInt16();

                ushort firstMatrixIndex = reader.ReadUInt16();
                ushort firstPacketIndex = reader.ReadUInt16();
                Trace.Assert(reader.ReadUInt16() == 0xFFFF); // Padding

                float   boundingSphereDiameter = reader.ReadSingle();
                Vector3 bboxMin = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
                Vector3 bboxMax = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());

                // Determine which Attributes this particular shape uses.
                reader.BaseStream.Position = tagStart + attributeOffset + batchAttributeOffset;
                List <ShapeVertexAttribute> attributes = new List <ShapeVertexAttribute>();
                do
                {
                    ShapeVertexAttribute attribute = new ShapeVertexAttribute((VertexArrayType)reader.ReadInt32(), (VertexDataType)reader.ReadInt32());
                    if (attribute.ArrayType == VertexArrayType.NullAttr)
                    {
                        break;
                    }

                    attributes.Add(attribute);
                } while (true);

                shape.BoundingSphereDiameter = boundingSphereDiameter;
                shape.BoundingBox            = new FAABox(bboxMin, bboxMax);
                shape.Attributes             = attributes;
                Shapes.Add(shape);

                int numVertexRead = 0;
                for (ushort p = 0; p < packetCount; p++)
                {
                    // The packets are all stored linearly and then they point to the specific size and offset of the data for this particular packet.
                    reader.BaseStream.Position = tagStart + packetLocationOffset + ((firstPacketIndex + p) * 0x8); /* 0x8 is the size of one Packet entry */

                    int packetSize   = reader.ReadInt32();
                    int packetOffset = reader.ReadInt32();

                    // Read Matrix Data for Packet
                    reader.BaseStream.Position = tagStart + matrixDataOffset + (firstMatrixIndex + p) * 0x08; /* 0x8 is the size of one Matrix Data */
                    ushort matrixUnknown0   = reader.ReadUInt16();
                    ushort matrixCount      = reader.ReadUInt16();
                    uint   matrixFirstIndex = reader.ReadUInt32();

                    Shape.SkinDataTable matrixData = new Shape.SkinDataTable(matrixUnknown0);
                    shape.MatrixDataTable.Add(matrixData);
                    matrixData.FirstRelevantVertexIndex = shape.VertexData.Position.Count;

                    // Read Matrix Table data. The Matrix Table is skinning information for the packet which indexes into the DRW1 section for more info.
                    reader.BaseStream.Position = tagStart + matrixTableOffset + (matrixFirstIndex * 0x2); /* 0x2 is the size of one Matrix Table entry */
                    for (int m = 0; m < matrixCount; m++)
                    {
                        matrixData.MatrixTable.Add(reader.ReadUInt16());
                    }

                    // Read the Primitive Data
                    reader.BaseStream.Position = tagStart + primitiveDataOffset + packetOffset;

                    uint numPrimitiveBytesRead = 0;
                    while (numPrimitiveBytesRead < packetSize)
                    {
                        // The game pads the chunk out with zeros, so if there's a primitive with type zero (invalid) then we early out of the loop.
                        GXPrimitiveType type = (GXPrimitiveType)reader.ReadByte();
                        if (type == 0 || numPrimitiveBytesRead >= packetSize)
                        {
                            break;
                        }

                        // The number of vertices this primitive has indexes for
                        ushort vertexCount = reader.ReadUInt16();
                        numPrimitiveBytesRead += 0x3; // 2 bytes for vertex count, one byte for GXPrimitiveType.

                        List <MeshVertexIndex> primitiveVertices = new List <MeshVertexIndex>();

                        for (int v = 0; v < vertexCount; v++)
                        {
                            MeshVertexIndex newVert = new MeshVertexIndex();
                            primitiveVertices.Add(newVert);

                            // Each vertex has an index for each ShapeAttribute specified by the Shape that we belong to. So we'll loop through
                            // each index and load it appropriately (as vertices can have different data sizes).
                            foreach (ShapeVertexAttribute curAttribute in attributes)
                            {
                                int  index        = 0;
                                uint numBytesRead = 0;

                                switch (curAttribute.DataType)
                                {
                                case VertexDataType.Unsigned8:
                                case VertexDataType.Signed8:
                                    index        = reader.ReadByte();
                                    numBytesRead = 1;
                                    break;

                                case VertexDataType.Unsigned16:
                                case VertexDataType.Signed16:
                                    index        = reader.ReadUInt16();
                                    numBytesRead = 2;
                                    break;

                                case VertexDataType.Float32:
                                case VertexDataType.None:
                                default:
                                    System.Console.WriteLine("Unknown Data Type {0} for ShapeAttribute!", curAttribute.DataType);
                                    break;
                                }

                                // We now have the index into the datatype this array points to. We can now inspect the array type of the
                                // attribute to get the value out of the correct source array.
                                switch (curAttribute.ArrayType)
                                {
                                case VertexArrayType.Position: newVert.Position = index; break;

                                case VertexArrayType.PositionMatrixIndex: newVert.PosMtxIndex = index; break;

                                case VertexArrayType.Normal: newVert.Normal = index; break;

                                case VertexArrayType.Color0: newVert.Color0 = index; break;

                                case VertexArrayType.Color1: newVert.Color1 = index; break;

                                case VertexArrayType.Tex0:  newVert.Tex0 = index; break;

                                case VertexArrayType.Tex1:  newVert.Tex1 = index; break;

                                case VertexArrayType.Tex2:  newVert.Tex2 = index; break;

                                case VertexArrayType.Tex3:  newVert.Tex3 = index; break;

                                case VertexArrayType.Tex4:  newVert.Tex4 = index; break;

                                case VertexArrayType.Tex5:  newVert.Tex5 = index; break;

                                case VertexArrayType.Tex6:  newVert.Tex6 = index; break;

                                case VertexArrayType.Tex7:  newVert.Tex7 = index; break;

                                default:
                                    System.Console.WriteLine("Unsupported ArrayType {0} for ShapeAttribute!", curAttribute.ArrayType);
                                    break;
                                }

                                numPrimitiveBytesRead += numBytesRead;
                            }
                        }

                        // All vertices have now been loaded into the primitiveIndexes array. We can now convert them if needed
                        // to triangle lists, instead of triangle fans, strips, etc.
                        var triangleList = ConvertTopologyToTriangles(type, primitiveVertices);
                        for (int i = 0; i < triangleList.Count; i++)
                        {
                            shape.Indexes.Add(numVertexRead);
                            numVertexRead++;

                            var tri = triangleList[i];
                            if (tri.Position >= 0)
                            {
                                shape.VertexData.Position.Add(compressedVertexData.Position[tri.Position]);
                            }
                            if (tri.Normal >= 0)
                            {
                                shape.VertexData.Normal.Add(compressedVertexData.Normal[tri.Normal]);
                            }
                            if (tri.Binormal >= 0)
                            {
                                shape.VertexData.Binormal.Add(compressedVertexData.Binormal[tri.Binormal]);
                            }
                            if (tri.Color0 >= 0)
                            {
                                shape.VertexData.Color0.Add(compressedVertexData.Color0[tri.Color0]);
                            }
                            if (tri.Color1 >= 0)
                            {
                                shape.VertexData.Color1.Add(compressedVertexData.Color1[tri.Color1]);
                            }
                            if (tri.Tex0 >= 0)
                            {
                                shape.VertexData.Tex0.Add(compressedVertexData.Tex0[tri.Tex0]);
                            }
                            if (tri.Tex1 >= 0)
                            {
                                shape.VertexData.Tex1.Add(compressedVertexData.Tex1[tri.Tex1]);
                            }
                            if (tri.Tex2 >= 0)
                            {
                                shape.VertexData.Tex2.Add(compressedVertexData.Tex2[tri.Tex2]);
                            }
                            if (tri.Tex3 >= 0)
                            {
                                shape.VertexData.Tex3.Add(compressedVertexData.Tex3[tri.Tex3]);
                            }
                            if (tri.Tex4 >= 0)
                            {
                                shape.VertexData.Tex4.Add(compressedVertexData.Tex4[tri.Tex4]);
                            }
                            if (tri.Tex5 >= 0)
                            {
                                shape.VertexData.Tex5.Add(compressedVertexData.Tex5[tri.Tex5]);
                            }
                            if (tri.Tex6 >= 0)
                            {
                                shape.VertexData.Tex6.Add(compressedVertexData.Tex6[tri.Tex6]);
                            }
                            if (tri.Tex7 >= 0)
                            {
                                shape.VertexData.Tex7.Add(compressedVertexData.Tex7[tri.Tex7]);
                            }

                            // We pre-divide the index here just to make life simpler. For some reason the index is multiplied by three
                            // and it's not entirely clear why. Might be related to doing skinning on the GPU and offsetting the correct
                            // number of floats in a matrix?
                            if (tri.PosMtxIndex >= 0)
                            {
                                shape.VertexData.PositionMatrixIndexes.Add(tri.PosMtxIndex / 3);
                            }
                            else
                            {
                                shape.VertexData.PositionMatrixIndexes.Add(0);
                            }
                        }
                    }

                    // Set the last relevant vertex for this packet.
                    matrixData.LastRelevantVertexIndex = shape.VertexData.Position.Count;
                }

                shape.UploadBuffersToGPU(false);
            }
        }
Ejemplo n.º 4
0
        public void LoadVTX1FromStream(EndianBinaryReader reader, long chunkStart, int chunkSize)
        {
            int vertexFormatOffset = reader.ReadInt32();

            int[] vertexDataOffsets = new int[13];
            for (int i = 0; i < 13; i++)
            {
                vertexDataOffsets[i] = reader.ReadInt32();
            }

            reader.BaseStream.Position = chunkStart + vertexFormatOffset;

            VertexFormats = new List <VertexFormat>();
            VertexFormat curFormat = null;

            do
            {
                curFormat                = new VertexFormat();
                curFormat.ArrayType      = (VertexArrayType)reader.ReadInt32();
                curFormat.ComponentCount = reader.ReadInt32();
                curFormat.DataType       = (VertexDataType)reader.ReadInt32();
                curFormat.ColorDataType  = (VertexColorType)curFormat.DataType;
                curFormat.DecimalPoint   = reader.ReadByte();
                reader.ReadBytes(3); // Padding
                VertexFormats.Add(curFormat);
            }while (curFormat.ArrayType != VertexArrayType.NullAttr);

            // Remove the last one because it simply the NullAttr that defines the end of the list.
            VertexFormats.RemoveAt(VertexFormats.Count - 1);

            VertexData = new MeshVertexHolder();

            // Retrieve the data from the 13 possible types of data using the above VertexFormats as a guide to the data.
            for (int k = 0; k < vertexDataOffsets.Length; k++)
            {
                // If this data isn't included in the file, it'll list zero as its offset.
                if (vertexDataOffsets[k] == 0)
                {
                    continue;
                }

                // Get the total length of this block of data. This is used to try and automate a lot of the data loading.
                int totalLength = GetVertexDataLength(vertexDataOffsets, k, chunkSize);
                reader.BaseStream.Position = chunkStart + vertexDataOffsets[k];

                VertexFormat vertexFormat = null;

                switch (k)
                {
                // Position Data
                case 0:
                    vertexFormat        = VertexFormats.Find(x => x.ArrayType == VertexArrayType.Position);
                    VertexData.Position = LoadVertexAttribute <Vector3>(reader, totalLength, vertexFormat.DecimalPoint, VertexArrayType.Position, vertexFormat.DataType, VertexColorType.None);
                    break;

                // Normal Data
                case 1:
                    vertexFormat      = VertexFormats.Find(x => x.ArrayType == VertexArrayType.Normal);
                    VertexData.Normal = LoadVertexAttribute <Vector3>(reader, totalLength, vertexFormat.DecimalPoint, VertexArrayType.Normal, vertexFormat.DataType, VertexColorType.None);
                    break;

                // Normal Binormal Tangent Data (presumed)
                case 2:
                    vertexFormat        = VertexFormats.Find(x => x.ArrayType == VertexArrayType.NormalBinormalTangent);
                    VertexData.Binormal = LoadVertexAttribute <Vector3>(reader, totalLength, vertexFormat.DecimalPoint, VertexArrayType.NormalBinormalTangent, vertexFormat.DataType, VertexColorType.None);
                    break;

                // Color 0 Data
                case 3:
                    vertexFormat      = VertexFormats.Find(x => x.ArrayType == VertexArrayType.Color0);
                    VertexData.Color0 = LoadVertexAttribute <WLinearColor>(reader, totalLength, vertexFormat.DecimalPoint, VertexArrayType.Color0, VertexDataType.None, vertexFormat.ColorDataType);
                    break;

                // Color 1 Data (presumed)
                case 4:
                    vertexFormat      = VertexFormats.Find(x => x.ArrayType == VertexArrayType.Color1);
                    VertexData.Color1 = LoadVertexAttribute <WLinearColor>(reader, totalLength, vertexFormat.DecimalPoint, VertexArrayType.Color1, VertexDataType.None, vertexFormat.ColorDataType);
                    break;

                // Tex 0 Data
                case 5:
                    vertexFormat    = VertexFormats.Find(x => x.ArrayType == VertexArrayType.Tex0);
                    VertexData.Tex0 = LoadVertexAttribute <Vector2>(reader, totalLength, vertexFormat.DecimalPoint, VertexArrayType.Tex0, vertexFormat.DataType, VertexColorType.None);
                    break;

                // Tex 1 Data
                case 6:
                    vertexFormat    = VertexFormats.Find(x => x.ArrayType == VertexArrayType.Tex1);
                    VertexData.Tex1 = LoadVertexAttribute <Vector2>(reader, totalLength, vertexFormat.DecimalPoint, VertexArrayType.Tex1, vertexFormat.DataType, VertexColorType.None);
                    break;

                // Tex 2 Data
                case 7:
                    vertexFormat    = VertexFormats.Find(x => x.ArrayType == VertexArrayType.Tex2);
                    VertexData.Tex2 = LoadVertexAttribute <Vector2>(reader, totalLength, vertexFormat.DecimalPoint, VertexArrayType.Tex2, vertexFormat.DataType, VertexColorType.None);
                    break;

                // Tex 3 Data
                case 8:
                    vertexFormat    = VertexFormats.Find(x => x.ArrayType == VertexArrayType.Tex3);
                    VertexData.Tex3 = LoadVertexAttribute <Vector2>(reader, totalLength, vertexFormat.DecimalPoint, VertexArrayType.Tex3, vertexFormat.DataType, VertexColorType.None);
                    break;

                // Tex 4 Data
                case 9:
                    vertexFormat    = VertexFormats.Find(x => x.ArrayType == VertexArrayType.Tex4);
                    VertexData.Tex4 = LoadVertexAttribute <Vector2>(reader, totalLength, vertexFormat.DecimalPoint, VertexArrayType.Tex4, vertexFormat.DataType, VertexColorType.None);
                    break;

                // Tex 5 Data
                case 10:
                    vertexFormat    = VertexFormats.Find(x => x.ArrayType == VertexArrayType.Tex5);
                    VertexData.Tex5 = LoadVertexAttribute <Vector2>(reader, totalLength, vertexFormat.DecimalPoint, VertexArrayType.Tex5, vertexFormat.DataType, VertexColorType.None);
                    break;

                // Tex 6 Data
                case 11:
                    vertexFormat    = VertexFormats.Find(x => x.ArrayType == VertexArrayType.Tex6);
                    VertexData.Tex6 = LoadVertexAttribute <Vector2>(reader, totalLength, vertexFormat.DecimalPoint, VertexArrayType.Tex6, vertexFormat.DataType, VertexColorType.None);
                    break;

                // Tex 7 Data
                case 12:
                    vertexFormat    = VertexFormats.Find(x => x.ArrayType == VertexArrayType.Tex7);
                    VertexData.Tex7 = LoadVertexAttribute <Vector2>(reader, totalLength, vertexFormat.DecimalPoint, VertexArrayType.Tex7, vertexFormat.DataType, VertexColorType.None);
                    break;

                default:
                    Console.WriteLine("Unsupported VertexFormat Index: {0}", k);
                    break;
                }
            }
        }