コード例 #1
0
        public GFSubMesh(H3DSubMesh SubMesh, H3DMesh Parent, List <PICAVertex> Vertices, string Name) : this()
        {
            this.Name        = Name;
            BoneIndicesCount = (byte)SubMesh.BoneIndicesCount;
            BoneIndices      = new byte[SubMesh.BoneIndicesCount];
            for (int i = 0; i < SubMesh.BoneIndicesCount; i++)
            {
                BoneIndices[i] = (byte)SubMesh.BoneIndices[i];
            }

            Indices = SubMesh.Indices;

            PrimitiveMode = SubMesh.PrimitiveMode;
            VertexStride  = Parent.VertexStride;

            Attributes = Parent.Attributes;

            foreach (PICAFixedAttribute Old in Parent.FixedAttributes)
            {
                PICAFixedAttribute New = new PICAFixedAttribute()
                {
                    Name  = Old.Name,
                    Value = Old.Value
                };
                FixedAttributes.Add(New);
            }

            List <PICAVertex>           NewVertices    = new List <PICAVertex>();
            Dictionary <ushort, ushort> OldNewIndexMap = new Dictionary <ushort, ushort>();

            ushort[] NewIndices = new ushort[Indices.Length];

            for (int i = 0; i < NewIndices.Length; i++)
            {
                if (OldNewIndexMap.ContainsKey(Indices[i]))
                {
                    NewIndices[i] = OldNewIndexMap[Indices[i]];
                }
                else
                {
                    PICAVertex Vertex   = Vertices[Indices[i]];
                    ushort     NewIndex = (ushort)NewVertices.Count;
                    NewVertices.Add(Vertex);
                    NewIndices[i] = NewIndex;
                    OldNewIndexMap.Add(Indices[i], NewIndex);
                }
            }

            Indices    = NewIndices;
            IsIdx8Bits = /*NewIndices.Length <= 0x100*/ false;
            RawBuffer  = VerticesConverter.GetBuffer(NewVertices, Attributes);
        }
コード例 #2
0
ファイル: GFMesh.cs プロジェクト: HelloOO7/SPICA
        public void Write(BinaryWriter Writer)
        {
            long StartPosition = Writer.BaseStream.Position;

            new GFSection(MagicStr).Write(Writer);

            GFNV1 FNV = new GFNV1();

            FNV.Hash(Name);

            Writer.Write(FNV.HashCode);
            Writer.WritePaddedString(Name, 0x40);

            Writer.Write(0u);

            Writer.Write(BBoxMinVector);
            Writer.Write(BBoxMaxVector);

            Writer.Write((uint)SubMeshes.Count);

            Writer.Write(BoneIndicesPerVertex);

            Writer.Write(0xfffffffffffffffful);
            Writer.Write(0xfffffffffffffffful);

            for (int Index = 0; Index < SubMeshes.Count; Index++)
            {
                GFSubMesh SM = SubMeshes[Index];

                PICACommandWriter CmdWriter;

                /* Enable commands */
                CmdWriter = new PICACommandWriter();

                ulong BufferFormats     = 0;
                ulong BufferAttributes  = 0;
                ulong BufferPermutation = 0;
                int   AttributesTotal   = 0;

                //Normal Attributes
                for (int Attr = 0; Attr < SM.Attributes.Count; Attr++)
                {
                    PICAAttribute Attrib = SM.Attributes[Attr];

                    int Shift = AttributesTotal++ *4;

                    ulong AttribFmt;

                    AttribFmt  = (ulong)Attrib.Format;
                    AttribFmt |= (ulong)((Attrib.Elements - 1) & 3) << 2;

                    BufferFormats     |= AttribFmt << Shift;
                    BufferPermutation |= (ulong)Attrib.Name << Shift;
                    BufferAttributes  |= (ulong)Attr << Shift;
                }

                BufferAttributes |= (ulong)(SM.VertexStride & 0xff) << 48;
                BufferAttributes |= (ulong)SM.Attributes.Count << 60;

                //Fixed Attributes
                foreach (PICAFixedAttribute Attrib in SM.FixedAttributes)
                {
                    BufferFormats |= 1ul << (48 + AttributesTotal);

                    BufferPermutation |= (ulong)Attrib.Name << AttributesTotal++ *4;
                }

                BufferFormats |= (ulong)(AttributesTotal - 1) << 60;

                CmdWriter.SetCommand(PICARegister.GPUREG_VSH_INPUTBUFFER_CONFIG, 0xa0000000u | (uint)(AttributesTotal - 1), 0xb);

                CmdWriter.SetCommand(PICARegister.GPUREG_VSH_NUM_ATTR, (uint)(AttributesTotal - 1), 1);

                CmdWriter.SetCommand(PICARegister.GPUREG_VSH_ATTRIBUTES_PERMUTATION_LOW, (uint)(BufferPermutation >> 0));
                CmdWriter.SetCommand(PICARegister.GPUREG_VSH_ATTRIBUTES_PERMUTATION_HIGH, (uint)(BufferPermutation >> 32));

                CmdWriter.SetCommand(PICARegister.GPUREG_ATTRIBBUFFERS_LOC, true,
                                     0x03000000u, //Base Address (Place holder)
                                     (uint)(BufferFormats >> 0),
                                     (uint)(BufferFormats >> 32),
                                     0x99999999u, //Attributes Buffer Address (Place holder)
                                     (uint)(BufferAttributes >> 0),
                                     (uint)(BufferAttributes >> 32));

                for (int Attr = 0; Attr < SM.FixedAttributes.Count; Attr++)
                {
                    PICAFixedAttribute Attrib = SM.FixedAttributes[Attr];

                    float Scale =
                        Attrib.Name == PICAAttributeName.Color ||
                        Attrib.Name == PICAAttributeName.BoneWeight ? GFMesh.Scales[1] : 1;

                    PICAFixedAttribute ScaledAttribute = new PICAFixedAttribute()
                    {
                        Name  = Attrib.Name,
                        Value = new PICAVectorFloat24(Attrib.Value.X, Attrib.Value.Y, Attrib.Value.Z, Attrib.Value.W) / Scale
                    };

                    CmdWriter.SetCommand(PICARegister.GPUREG_FIXEDATTRIB_INDEX, true,
                                         (uint)(SM.Attributes.Count + Attr),
                                         ScaledAttribute.Value.Word0,
                                         ScaledAttribute.Value.Word1,
                                         ScaledAttribute.Value.Word2);
                }

                CmdWriter.WriteEnd();

                WriteCmdsBuff(Writer, CmdWriter.GetBuffer(), Index * 3);

                /* Disable commands */
                CmdWriter = new PICACommandWriter();

                //Assuming that the Position isn't used as Fixed Attribute since this doesn't make sense.
                CmdWriter.SetCommand(PICARegister.GPUREG_ATTRIBBUFFER0_OFFSET, true, 0, 0, 0);

                for (int Attr = 1; Attr < 12; Attr++)
                {
                    CmdWriter.SetCommand(PICARegister.GPUREG_ATTRIBBUFFER0_CONFIG2 + Attr * 3, 0);

                    if (SM.FixedAttributes?.Any(x => (int)x.Name == Attr) ?? false)
                    {
                        CmdWriter.SetCommand(PICARegister.GPUREG_FIXEDATTRIB_INDEX, true, (uint)Attr, 0, 0, 0);
                    }
                }

                CmdWriter.WriteEnd();

                WriteCmdsBuff(Writer, CmdWriter.GetBuffer(), Index * 3 + 1);

                /* Index commands */
                CmdWriter = new PICACommandWriter();

                uint IdxFmtAddr = SM.IsIdx8Bits
                    ? 0x01999999u
                    : 0x81999999u;

                CmdWriter.SetCommand(PICARegister.GPUREG_RESTART_PRIMITIVE, true);

                CmdWriter.SetCommand(PICARegister.GPUREG_INDEXBUFFER_CONFIG, IdxFmtAddr);

                CmdWriter.SetCommand(PICARegister.GPUREG_NUMVERTICES, (uint)SM.Indices.Length);

                CmdWriter.SetCommand(PICARegister.GPUREG_START_DRAW_FUNC0, false, 1);

                CmdWriter.SetCommand(PICARegister.GPUREG_DRAWELEMENTS, true);

                CmdWriter.SetCommand(PICARegister.GPUREG_START_DRAW_FUNC0, true, 1);

                CmdWriter.SetCommand(PICARegister.GPUREG_VTX_FUNC, true);

                CmdWriter.SetCommand(PICARegister.GPUREG_PRIMITIVE_CONFIG, (uint)SM.PrimitiveMode << 8, 8);
                CmdWriter.SetCommand(PICARegister.GPUREG_PRIMITIVE_CONFIG, (uint)SM.PrimitiveMode << 8, 8);

                CmdWriter.WriteEnd();

                WriteCmdsBuff(Writer, CmdWriter.GetBuffer(), Index * 3 + 2);
            }

            foreach (GFSubMesh SM in SubMeshes)
            {
                FNV = new GFNV1();

                FNV.Hash(SM.Name);

                Writer.Write(FNV.HashCode);
                Writer.Write(GetPaddedLen4(SM.Name.Length));
                Writer.WritePaddedString(SM.Name, GetPaddedLen4(SM.Name.Length));

                Writer.Write(SM.BoneIndicesCount);

                byte[] BoneIndices = new byte[0x1f];

                SM.BoneIndices.CopyTo(BoneIndices, 0);

                Writer.Write(BoneIndices);

                int VerticesCount = 0;

                if (SM.VertexStride != 0)
                {
                    VerticesCount = SM.RawBuffer.Length / SM.VertexStride;
                }

                int VtxBuffLen = SM.RawBuffer.Length;
                int IdxBuffLen = SM.Indices.Length * (SM.IsIdx8Bits ? 1 : 2);

                Writer.Write(VerticesCount);
                Writer.Write(SM.Indices.Length);
                Writer.Write(GetPaddedLen16(VtxBuffLen));
                Writer.Write(GetPaddedLen16(IdxBuffLen));
            }

            foreach (GFSubMesh SM in SubMeshes)
            {
                long Position = Writer.BaseStream.Position;

                Writer.Write(SM.RawBuffer);

                int VertexBufferPaddingLength = GetPaddedLen16(SM.RawBuffer.Length) - SM.RawBuffer.Length;
                Writer.Write(new byte[VertexBufferPaddingLength]);

                /*while (((Writer.BaseStream.Position - Position) & 3) != 0)
                 * {
                 *  Writer.Write((byte)0);
                 * }*/

                Position = Writer.BaseStream.Position;

                foreach (ushort Idx in SM.Indices)
                {
                    if (SM.IsIdx8Bits)
                    {
                        Writer.Write((byte)Idx);
                    }
                    else
                    {
                        Writer.Write(Idx);
                    }
                }

                /*while (((Writer.BaseStream.Position - Position) & 0xf) != 0)
                 * {
                 *  Writer.Write((byte)0);
                 * }*/
                int IndexBufferLength        = SM.Indices.Length * (SM.IsIdx8Bits ? 1 : 2);
                int IndexBufferPaddingLength = GetPaddedLen16(IndexBufferLength) - IndexBufferLength;
                Writer.Write(new byte[IndexBufferPaddingLength]);
            }

            Writer.Align(0x10, 0);

            Writer.Write(0ul);
            Writer.Write(0ul);

            long EndPosition = Writer.BaseStream.Position;

            Writer.BaseStream.Seek(StartPosition + 8, SeekOrigin.Begin);

            Writer.Write((uint)(EndPosition - StartPosition - 0x10));

            Writer.BaseStream.Seek(EndPosition, SeekOrigin.Begin);
        }