Ejemplo n.º 1
0
        private static void Write(BinaryWriter Writer, PICAAttribute Attrib, Vector4 v, int i)
        {
            switch (i)
            {
            case 0: Write(Writer, Attrib, v.X); break;

            case 1: Write(Writer, Attrib, v.Y); break;

            case 2: Write(Writer, Attrib, v.Z); break;

            case 3: Write(Writer, Attrib, v.W); break;
            }
        }
Ejemplo n.º 2
0
        private static void Write(BinaryWriter Writer, PICAAttribute Attrib, float Value)
        {
            Value /= Attrib.Scale;

            if (Attrib.Format != PICAAttributeFormat.Float)
            {
                //Due to float lack of precision it's better to round the number,
                //because directly casting it will always use the lowest number that
                //may cause issues for values that float can't represent (like 0.1).
                Value = (float)Math.Round(Value);
            }

            switch (Attrib.Format)
            {
            case PICAAttributeFormat.Byte: Writer.Write((sbyte)Value); break;

            case PICAAttributeFormat.Ubyte: Writer.Write((byte)Value); break;

            case PICAAttributeFormat.Short: Writer.Write((short)Value); break;

            case PICAAttributeFormat.Float: Writer.Write(Value); break;
            }
        }
Ejemplo n.º 3
0
        public GFMesh(BinaryReader Reader) : this()
        {
            GFSection MeshSection = new GFSection(Reader);

            long Position = Reader.BaseStream.Position;

            uint   NameHash = Reader.ReadUInt32();
            string NameStr  = Reader.ReadPaddedString(0x40);

            Name = NameStr;

            Reader.ReadUInt32();

            BBoxMinVector = Reader.ReadVector4(); //Is it right? seems to be 0, 0, 0, 1
            BBoxMaxVector = Reader.ReadVector4(); //Is it right? seems to be 0, 0, 0, 1

            uint SubMeshesCount = Reader.ReadUInt32();

            BoneIndicesPerVertex = Reader.ReadInt32();

            Reader.BaseStream.Seek(0x10, SeekOrigin.Current); //Padding

            List <uint[]> CmdList = new List <uint[]>();

            uint CommandsLength;
            uint CommandIndex;
            uint CommandsCount;
            uint Padding;

            do
            {
                CommandsLength = Reader.ReadUInt32();
                CommandIndex   = Reader.ReadUInt32();
                CommandsCount  = Reader.ReadUInt32();
                Padding        = Reader.ReadUInt32();

                uint[] Commands = new uint[CommandsLength >> 2];

                for (int Index = 0; Index < Commands.Length; Index++)
                {
                    Commands[Index] = Reader.ReadUInt32();
                }

                CmdList.Add(Commands);
            }while (CommandIndex < CommandsCount - 1);

            SubMeshSize[] SMSizes = new SubMeshSize[SubMeshesCount];

            //Add SubMesh with Hash, Name and Bone Indices.
            //The rest is added latter (because the data is split inside the file).
            for (int MeshIndex = 0; MeshIndex < SubMeshesCount; MeshIndex++)
            {
                GFSubMesh SM = new GFSubMesh();

                uint SMNameHash = Reader.ReadUInt32();

                SM.Name             = Reader.ReadIntLengthString();
                SM.BoneIndicesCount = Reader.ReadByte();

                for (int Bone = 0; Bone < 0x1f; Bone++)
                {
                    SM.BoneIndices[Bone] = Reader.ReadByte();
                }

                SMSizes[MeshIndex] = new SubMeshSize()
                {
                    VerticesCount  = Reader.ReadInt32(),
                    IndicesCount   = Reader.ReadInt32(),
                    VerticesLength = Reader.ReadInt32(),
                    IndicesLength  = Reader.ReadInt32()
                };

                SubMeshes.Add(SM);
            }

            for (int MeshIndex = 0; MeshIndex < SubMeshesCount; MeshIndex++)
            {
                GFSubMesh SM = SubMeshes[MeshIndex];

                uint[] EnableCommands  = CmdList[MeshIndex * 3 + 0];
                uint[] DisableCommands = CmdList[MeshIndex * 3 + 1];
                uint[] IndexCommands   = CmdList[MeshIndex * 3 + 2];

                PICACommandReader CmdReader;

                CmdReader = new PICACommandReader(EnableCommands);

                PICAVectorFloat24[] Fixed = new PICAVectorFloat24[12];

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

                int FixedIndex = 0;

                while (CmdReader.HasCommand)
                {
                    PICACommand Cmd = CmdReader.GetCommand();

                    uint Param = Cmd.Parameters[0];

                    switch (Cmd.Register)
                    {
                    case PICARegister.GPUREG_ATTRIBBUFFERS_FORMAT_LOW:  BufferFormats |= (ulong)Param << 0; break;

                    case PICARegister.GPUREG_ATTRIBBUFFERS_FORMAT_HIGH: BufferFormats |= (ulong)Param << 32; break;

                    case PICARegister.GPUREG_ATTRIBBUFFER0_CONFIG1:
                        BufferAttributes |= Param;
                        break;

                    case PICARegister.GPUREG_ATTRIBBUFFER0_CONFIG2:
                        BufferAttributes |= (ulong)(Param & 0xffff) << 32;
                        SM.VertexStride   = (byte)(Param >> 16);
                        AttributesCount   = (int)(Param >> 28);
                        break;

                    case PICARegister.GPUREG_FIXEDATTRIB_INDEX: FixedIndex = (int)Param; break;

                    case PICARegister.GPUREG_FIXEDATTRIB_DATA0: Fixed[FixedIndex].Word0 = Param; break;

                    case PICARegister.GPUREG_FIXEDATTRIB_DATA1: Fixed[FixedIndex].Word1 = Param; break;

                    case PICARegister.GPUREG_FIXEDATTRIB_DATA2: Fixed[FixedIndex].Word2 = Param; break;

                    case PICARegister.GPUREG_VSH_NUM_ATTR: AttributesTotal = (int)(Param + 1); break;

                    case PICARegister.GPUREG_VSH_ATTRIBUTES_PERMUTATION_LOW:  BufferPermutation |= (ulong)Param << 0; break;

                    case PICARegister.GPUREG_VSH_ATTRIBUTES_PERMUTATION_HIGH: BufferPermutation |= (ulong)Param << 32; break;
                    }
                }

                for (int Index = 0; Index < AttributesTotal; Index++)
                {
                    if (((BufferFormats >> (48 + Index)) & 1) != 0)
                    {
                        PICAAttributeName Name = (PICAAttributeName)((BufferPermutation >> Index * 4) & 0xf);

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

                        SM.FixedAttributes.Add(new PICAFixedAttribute()
                        {
                            Name  = Name,
                            Value = Fixed[Index] * Scale
                        });
                    }
                    else
                    {
                        int PermutationIdx = (int)((BufferAttributes >> Index * 4) & 0xf);
                        int AttributeName  = (int)((BufferPermutation >> PermutationIdx * 4) & 0xf);
                        int AttributeFmt   = (int)((BufferFormats >> PermutationIdx * 4) & 0xf);

                        PICAAttribute Attrib = new PICAAttribute()
                        {
                            Name     = (PICAAttributeName)AttributeName,
                            Format   = (PICAAttributeFormat)(AttributeFmt & 3),
                            Elements = (AttributeFmt >> 2) + 1,
                            Scale    = Scales[AttributeFmt & 3]
                        };

                        if (Attrib.Name == PICAAttributeName.BoneIndex)
                        {
                            Attrib.Scale = 1;
                        }

                        SM.Attributes.Add(Attrib);
                    }
                }

                CmdReader = new PICACommandReader(IndexCommands);

                uint BufferAddress = 0;
                uint BufferCount   = 0;

                while (CmdReader.HasCommand)
                {
                    PICACommand Cmd = CmdReader.GetCommand();

                    uint Param = Cmd.Parameters[0];

                    switch (Cmd.Register)
                    {
                    case PICARegister.GPUREG_INDEXBUFFER_CONFIG: BufferAddress = Param; break;

                    case PICARegister.GPUREG_NUMVERTICES:        BufferCount = Param; break;

                    case PICARegister.GPUREG_PRIMITIVE_CONFIG:
                        SM.PrimitiveMode = (PICAPrimitiveMode)(Param >> 8);
                        break;
                    }
                }

                SM.RawBuffer = Reader.ReadBytes(SMSizes[MeshIndex].VerticesLength);

                SM.Indices = new ushort[BufferCount];

                long IndexAddress = Reader.BaseStream.Position;

                for (int Index = 0; Index < BufferCount; Index++)
                {
                    if ((BufferAddress >> 31) != 0)
                    {
                        SM.Indices[Index] = Reader.ReadUInt16();
                    }
                    else
                    {
                        SM.Indices[Index] = Reader.ReadByte();
                    }
                }

                Reader.BaseStream.Seek(IndexAddress + SMSizes[MeshIndex].IndicesLength, SeekOrigin.Begin);
            }

            Reader.BaseStream.Seek(Position + MeshSection.Length, SeekOrigin.Begin);
        }
Ejemplo n.º 4
0
        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);
        }
Ejemplo n.º 5
0
        public H3D ToH3D(string TextureSearchPath = null)
        {
            H3D Output = new H3D();

            H3DModel Model = new H3DModel();

            Model.Name = "Model";

            ushort MaterialIndex = 0;

            if (Skeleton.Count > 0)
            {
                Model.Flags = H3DModelFlags.HasSkeleton;
            }

            Model.BoneScaling = H3DBoneScaling.Maya;
            Model.MeshNodesVisibility.Add(true);

            foreach (SMDMesh Mesh in Meshes)
            {
                Vector3 MinVector = new Vector3();
                Vector3 MaxVector = new Vector3();

                Dictionary <PICAVertex, int> Vertices = new Dictionary <PICAVertex, int>();

                List <H3DSubMesh> SubMeshes = new List <H3DSubMesh>();

                Queue <PICAVertex> VerticesQueue = new Queue <PICAVertex>();

                foreach (PICAVertex Vertex in Mesh.Vertices)
                {
                    VerticesQueue.Enqueue(Vertex);
                }

                while (VerticesQueue.Count > 2)
                {
                    List <ushort> Indices     = new List <ushort>();
                    List <ushort> BoneIndices = new List <ushort>();

                    int TriCount = VerticesQueue.Count / 3;

                    while (TriCount-- > 0)
                    {
                        PICAVertex[] Triangle = new PICAVertex[3];

                        Triangle[0] = VerticesQueue.Dequeue();
                        Triangle[1] = VerticesQueue.Dequeue();
                        Triangle[2] = VerticesQueue.Dequeue();

                        List <ushort> TempIndices = new List <ushort>();

                        for (int Tri = 0; Tri < 3; Tri++)
                        {
                            PICAVertex Vertex = Triangle[Tri];

                            for (int i = 0; i < 4; i++)
                            {
                                ushort Index = (ushort)Vertex.Indices[i];

                                if (!(BoneIndices.Contains(Index) || TempIndices.Contains(Index)))
                                {
                                    TempIndices.Add(Index);
                                }
                            }
                        }

                        if (BoneIndices.Count + TempIndices.Count > 20)
                        {
                            VerticesQueue.Enqueue(Triangle[0]);
                            VerticesQueue.Enqueue(Triangle[1]);
                            VerticesQueue.Enqueue(Triangle[2]);

                            continue;
                        }

                        for (int Tri = 0; Tri < 3; Tri++)
                        {
                            PICAVertex Vertex = Triangle[Tri];

                            for (int Index = 0; Index < 4; Index++)
                            {
                                int BoneIndex = BoneIndices.IndexOf((ushort)Vertex.Indices[Index]);

                                if (BoneIndex == -1)
                                {
                                    BoneIndex = BoneIndices.Count;
                                    BoneIndices.Add((ushort)Vertex.Indices[Index]);
                                }

                                Vertex.Indices[Index] = BoneIndex;
                            }

                            if (Vertices.ContainsKey(Vertex))
                            {
                                Indices.Add((ushort)Vertices[Vertex]);
                            }
                            else
                            {
                                Indices.Add((ushort)Vertices.Count);

                                if (Vertex.Position.X < MinVector.X)
                                {
                                    MinVector.X = Vertex.Position.X;
                                }
                                if (Vertex.Position.Y < MinVector.Y)
                                {
                                    MinVector.Y = Vertex.Position.Y;
                                }
                                if (Vertex.Position.Z < MinVector.Z)
                                {
                                    MinVector.Z = Vertex.Position.Z;
                                }

                                if (Vertex.Position.X > MaxVector.X)
                                {
                                    MaxVector.X = Vertex.Position.X;
                                }
                                if (Vertex.Position.Y > MaxVector.Y)
                                {
                                    MaxVector.Y = Vertex.Position.Y;
                                }
                                if (Vertex.Position.Z > MaxVector.Z)
                                {
                                    MaxVector.Z = Vertex.Position.Z;
                                }

                                Vertices.Add(Vertex, Vertices.Count);
                            }
                        }
                    }

                    SubMeshes.Add(new H3DSubMesh()
                    {
                        Skinning         = H3DSubMeshSkinning.Smooth,
                        BoneIndicesCount = (ushort)BoneIndices.Count,
                        BoneIndices      = BoneIndices.ToArray(),
                        Indices          = Indices.ToArray()
                    });
                }

                List <PICAAttribute> Attributes = PICAAttribute.GetAttributes(
                    PICAAttributeName.Position,
                    PICAAttributeName.Normal,
                    PICAAttributeName.Color,
                    PICAAttributeName.TexCoord0,
                    PICAAttributeName.BoneIndex,
                    PICAAttributeName.BoneWeight);

                //Mesh
                H3DMesh M = new H3DMesh(Vertices.Keys, Attributes, SubMeshes)
                {
                    Skinning      = H3DMeshSkinning.Smooth,
                    MeshCenter    = (MinVector + MaxVector) * 0.5f,
                    MaterialIndex = MaterialIndex
                };

                //Material
                string TexName = Path.GetFileNameWithoutExtension(Mesh.MaterialName);
                string MatName = $"Mat{MaterialIndex++.ToString("D5")}_{TexName}";

                H3DMaterial Material = H3DMaterial.GetSimpleMaterial(Model.Name, MatName, TexName);

                Model.Materials.Add(Material);

                if (TextureSearchPath != null && !Output.Textures.Contains(TexName))
                {
                    string TextureFile = Path.Combine(TextureSearchPath, Mesh.MaterialName);

                    if (File.Exists(TextureFile))
                    {
                        Output.Textures.Add(new H3DTexture(TextureFile));
                    }
                }

                M.UpdateBoolUniforms(Material);

                Model.AddMesh(M);
            }

            //Build Skeleton
            foreach (SMDBone Bone in Skeleton)
            {
                SMDNode Node = Nodes[Bone.NodeIndex];

                Model.Skeleton.Add(new H3DBone()
                {
                    Name        = Node.Name,
                    ParentIndex = (short)Node.ParentIndex,
                    Translation = Bone.Translation,
                    Rotation    = Bone.Rotation,
                    Scale       = Vector3.One
                });
            }

            //Calculate Absolute Inverse Transforms for all bones
            foreach (H3DBone Bone in Model.Skeleton)
            {
                Bone.CalculateTransform(Model.Skeleton);
            }

            Output.Models.Add(Model);

            Output.CopyMaterials();

            return(Output);
        }
Ejemplo n.º 6
0
        public MTAttributesGroup(BinaryReader Reader, uint StringsTblAddr)
        {
            byte   AttrId    = Reader.ReadByte();   //?
            ushort AttrCount = Reader.ReadUInt16(); //Bits 4-15 = Total attributes count
            byte   Stride    = Reader.ReadByte();   //In Word Count (32-bits)
            uint   Padding   = Reader.ReadUInt32(); //Not sure but seems to be always 0 so padding I guess

            AttrCount >>= 4;

            Stride *= 4;

            int RealOffset = 0;

            Attributes = new List <PICAAttribute>();

            for (int j = 0; j < AttrCount; j++)
            {
                string Name = MTShaderEffects.GetName(Reader, StringsTblAddr);

                uint Format = Reader.ReadUInt32();

                uint AttrIndex  = (Format >> 0) & 0x3f;  //Used when attribute is repeated usually
                uint AttrFormat = (Format >> 6) & 0x1f;  //See AttributeFormat enumerator
                uint AttrElems  = (Format >> 11) & 0x3;  //2 = 2D, 3 = 3D, 4 = 4D, ...
                uint AttrOffset = (Format >> 24) & 0xff; //In Word Count (32-bits)

                AttrOffset *= 4;

                PICAAttribute Attr = new PICAAttribute();

                switch (Name.ToLower())
                {
                case "position": Attr.Name = PICAAttributeName.Position;   break;

                case "normal":   Attr.Name = PICAAttributeName.Normal;     break;

                case "tangent":  Attr.Name = PICAAttributeName.Tangent;    break;

                case "color":    Attr.Name = PICAAttributeName.Color;      break;

                case "joint":    Attr.Name = PICAAttributeName.BoneIndex;  break;

                case "weight":   Attr.Name = PICAAttributeName.BoneWeight; break;

                case "texcoord":
                    if (AttrIndex < 3)
                    {
                        Attr.Name = (PICAAttributeName)((uint)PICAAttributeName.TexCoord0 + AttrIndex);
                    }
                    else
                    {
                        Attr.Name = PICAAttributeName.UserAttribute0;
                    } break;

                default: Attr.Name = PICAAttributeName.UserAttribute0; break;
                }

                bool Norm = false;

                int Size = 1;

                switch ((AttributeFormat)AttrFormat)
                {
                case AttributeFormat.F32:  Attr.Format = PICAAttributeFormat.Float; Norm = false; Size = 4; break;

                case AttributeFormat.S16:  Attr.Format = PICAAttributeFormat.Short; Norm = false; Size = 2; break;

                case AttributeFormat.S16N: Attr.Format = PICAAttributeFormat.Short; Norm = true;  Size = 2; break;

                case AttributeFormat.S8:   Attr.Format = PICAAttributeFormat.Byte;  Norm = false; Size = 1; break;

                case AttributeFormat.U8:   Attr.Format = PICAAttributeFormat.Ubyte; Norm = false; Size = 1; break;

                case AttributeFormat.S8N:  Attr.Format = PICAAttributeFormat.Byte;  Norm = true;  Size = 1; break;

                case AttributeFormat.U8N:  Attr.Format = PICAAttributeFormat.Ubyte; Norm = true;  Size = 1; break;

                case AttributeFormat.RGB:  Attr.Format = PICAAttributeFormat.Ubyte; Norm = true;  Size = 1; break;

                case AttributeFormat.RGBA: Attr.Format = PICAAttributeFormat.Ubyte; Norm = true;  Size = 1; break;
                }

                Attr.Scale = Norm ? Scales[(int)Attr.Format] : 1;

                Attr.Elements = (int)AttrElems;

                Attributes.Add(Attr);

                RealOffset += (int)(Size * AttrElems);

                if (RealOffset >= Stride)
                {
                    break;
                }
            }
        }
Ejemplo n.º 7
0
        public H3D ToH3D(string TextureAndMtlSearchPath = null, bool noTextures = false)
        {
            H3D Output = new H3D();

            Dictionary <string, OBJMaterial> Materials = new Dictionary <string, OBJMaterial>();

            if (TextureAndMtlSearchPath != null)
            {
                TextReader Reader = null;
                if (textureOnly)
                {
                    Reader = new StreamReader(textureOnlyFile);
                }
                else
                {
                    string MaterialFile = Path.Combine(TextureAndMtlSearchPath, MtlFile);

                    if (File.Exists(MaterialFile))
                    {
                        Reader = new StreamReader(MaterialFile);
                    }
                }
                if (Reader != null)
                {
                    string MaterialName = null;

                    OBJMaterial Material = default(OBJMaterial);

                    for (string Line; (Line = Reader.ReadLine()) != null;)
                    {
                        string[] Params = Line.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);

                        if (Params.Length == 0)
                        {
                            continue;
                        }

                        switch (Params[0])
                        {
                        case "newmtl":
                            if (Params.Length > 1)
                            {
                                if (MaterialName != null && Material.DiffuseTexture != null)
                                {
                                    Materials.Add(MaterialName, Material);
                                }

                                Material = new OBJMaterial();

                                MaterialName = Line.Substring(Line.IndexOf(" ")).Trim();
                            }
                            break;

                        case "map_Kd":
                            if (Params.Length > 1)
                            {
                                string Name = Line.Substring(Line.IndexOf(Params[1]));

                                string TextureFile = Path.Combine(TextureAndMtlSearchPath, Name);
                                string TextureName = Path.GetFileName(TextureFile);

                                if (File.Exists(TextureFile) && !noTextures)
                                {
                                    if (Output.Textures.Contains(TextureName))
                                    {
                                        Output.Textures.Remove(Output.Textures[Output.Textures.Find(TextureName)]);
                                    }
                                    Output.Textures.Add(new H3DTexture(TextureFile));
                                }

                                Material.DiffuseTexture = TextureName;
                            }
                            break;

                        case "Ka":
                        case "Kd":
                        case "Ks":
                            if (Params.Length >= 4)
                            {
                                Vector4 Color = new Vector4(
                                    float.Parse(Params[1], CultureInfo.InvariantCulture),
                                    float.Parse(Params[2], CultureInfo.InvariantCulture),
                                    float.Parse(Params[3], CultureInfo.InvariantCulture), 1);

                                switch (Params[0])
                                {
                                case "Ka": Material.Ambient = Color; break;

                                case "Kd": Material.Diffuse = Color; break;

                                case "Ks": Material.Specular = Color; break;
                                }
                            }
                            break;
                        }
                    }

                    Reader.Dispose();

                    if (MaterialName != null && !textureOnly)
                    {
                        Materials.Add(MaterialName, Material);
                    }
                }
            }

            if (!textureOnly)
            {
                H3DModel Model = new H3DModel();

                string newName = Microsoft.VisualBasic.Interaction.InputBox("Enter model name: ", "Name", Model.Name);

                if (newName != "")
                {
                    Model.Name = newName;
                }

                ushort MaterialIndex = 0;

                Model.Flags       = 0;
                Model.BoneScaling = H3DBoneScaling.Standard;
                Model.MeshNodesVisibility.Clear();
                Model.Skeleton.Clear();
                Model.MeshNodesVisibility.Add(true);

                float Height = 0;

                Meshes.Sort((x, y) => string.Compare(x.Name, y.Name));

                foreach (OBJMesh Mesh in Meshes)
                {
                    Vector3 MinVector = new Vector3();
                    Vector3 MaxVector = new Vector3();

                    Dictionary <PICAVertex, int> Vertices = new Dictionary <PICAVertex, int>();

                    List <H3DSubMesh> SubMeshes = new List <H3DSubMesh>();

                    Queue <PICAVertex> VerticesQueue = new Queue <PICAVertex>();

                    foreach (PICAVertex Vertex in Mesh.Vertices)
                    {
                        VerticesQueue.Enqueue(Vertex);
                    }

                    while (VerticesQueue.Count > 2)
                    {
                        List <ushort> Indices = new List <ushort>();

                        while (VerticesQueue.Count > 0)
                        {
                            for (int Tri = 0; Tri < 3; Tri++)
                            {
                                PICAVertex Vertex = VerticesQueue.Dequeue();

                                if (Mesh.Name.Contains("uncolor"))
                                {
                                    Vertex.Color = Vector4.One;
                                }

                                if (Vertices.ContainsKey(Vertex))
                                {
                                    Indices.Add((ushort)Vertices[Vertex]);
                                }
                                else
                                {
                                    Indices.Add((ushort)Vertices.Count);

                                    if (Vertex.Position.X < MinVector.X)
                                    {
                                        MinVector.X = Vertex.Position.X;
                                    }
                                    if (Vertex.Position.Y < MinVector.Y)
                                    {
                                        MinVector.Y = Vertex.Position.Y;
                                    }
                                    if (Vertex.Position.Z < MinVector.Z)
                                    {
                                        MinVector.Z = Vertex.Position.Z;
                                    }

                                    if (Vertex.Position.X > MaxVector.X)
                                    {
                                        MaxVector.X = Vertex.Position.X;
                                    }
                                    if (Vertex.Position.Y > MaxVector.Y)
                                    {
                                        MaxVector.Y = Vertex.Position.Y;
                                    }
                                    if (Vertex.Position.Z > MaxVector.Z)
                                    {
                                        MaxVector.Z = Vertex.Position.Z;
                                    }

                                    Vertices.Add(Vertex, Vertices.Count);
                                }
                            }
                        }

                        H3DSubMesh SM = new H3DSubMesh();

                        SM.BoneIndices = new ushort[] { };
                        SM.Skinning    = H3DSubMeshSkinning.None;
                        SM.Indices     = Indices.ToArray();

                        SubMeshes.Add(SM);
                    }

                    //Mesh
                    List <PICAAttribute> Attributes = PICAAttribute.GetAttributes(
                        PICAAttributeName.Position,
                        PICAAttributeName.Normal,
                        PICAAttributeName.TexCoord0,
                        PICAAttributeName.Color
                        );

                    H3DMesh M = new H3DMesh(Vertices.Keys, Attributes, SubMeshes)
                    {
                        Skinning      = H3DMeshSkinning.Rigid,
                        MeshCenter    = (MinVector + MaxVector) * 0.5f,
                        MaterialIndex = MaterialIndex,
                    };

                    if (Height < MaxVector.Y)
                    {
                        Height = MaxVector.Y;
                    }

                    //Material
                    string MatName = $"Mat{MaterialIndex++.ToString("D5")}_{Mesh.MaterialName}";

                    H3DMaterial Material = H3DMaterial.GetSimpleMaterial(Model.Name, Mesh.MaterialName, Materials[Mesh.MaterialName].DiffuseTexture);

                    Material.Texture0Name = Materials[Mesh.MaterialName].DiffuseTexture;

                    Material.MaterialParams.FaceCulling      = PICAFaceCulling.BackFace;
                    Material.MaterialParams.Flags            = H3DMaterialFlags.IsFragmentLightingEnabled | H3DMaterialFlags.IsVertexLightingEnabled | H3DMaterialFlags.IsFragmentLightingPolygonOffsetDirty;
                    Material.MaterialParams.FragmentFlags    = 0;
                    Material.MaterialParams.LightSetIndex    = 0;
                    Material.MaterialParams.FogIndex         = 0;
                    Material.MaterialParams.LogicalOperation = PICALogicalOp.Noop;

                    Material.MaterialParams.AmbientColor        = RGBA.White;
                    Material.MaterialParams.DiffuseColor        = RGBA.White;
                    Material.MaterialParams.EmissionColor       = RGBA.Black;
                    Material.MaterialParams.Specular0Color      = RGBA.Black;
                    Material.MaterialParams.Specular1Color      = RGBA.Black;
                    Material.MaterialParams.Constant0Color      = RGBA.White;
                    Material.MaterialParams.Constant1Color      = RGBA.White;
                    Material.MaterialParams.Constant2Color      = RGBA.White;
                    Material.MaterialParams.Constant3Color      = RGBA.White;
                    Material.MaterialParams.Constant4Color      = RGBA.White;
                    Material.MaterialParams.Constant5Color      = RGBA.White;
                    Material.MaterialParams.BlendColor          = RGBA.Black;
                    Material.MaterialParams.Constant2Assignment = 2;

                    Material.MaterialParams.ColorScale = 1;

                    Material.MaterialParams.FresnelSelector   = H3DFresnelSelector.No;
                    Material.MaterialParams.BumpMode          = H3DBumpMode.NotUsed;
                    Material.MaterialParams.BumpTexture       = 0;
                    Material.MaterialParams.PolygonOffsetUnit = 0;

                    Material.MaterialParams.TexEnvBufferColor = RGBA.White;

                    Material.MaterialParams.ColorOperation.FragOpMode = PICAFragOpMode.Default;
                    Material.MaterialParams.ColorOperation.BlendMode  = PICABlendMode.Blend;

                    Material.MaterialParams.ColorBufferRead  = true;
                    Material.MaterialParams.ColorBufferWrite = true;

                    Material.MaterialParams.StencilBufferRead  = true;
                    Material.MaterialParams.StencilBufferWrite = true;

                    Material.MaterialParams.DepthBufferRead                   = true;
                    Material.MaterialParams.DepthBufferWrite                  = false;
                    Material.MaterialParams.TexEnvStages[0].Source.Color      = new PICATextureCombinerSource[] { PICATextureCombinerSource.Texture0, PICATextureCombinerSource.PrimaryColor, PICATextureCombinerSource.Texture0 };
                    Material.MaterialParams.TexEnvStages[0].Source.Alpha      = new PICATextureCombinerSource[] { PICATextureCombinerSource.Texture0, PICATextureCombinerSource.Texture0, PICATextureCombinerSource.Texture0 };
                    Material.MaterialParams.TexEnvStages[0].Operand.Color     = new PICATextureCombinerColorOp[] { PICATextureCombinerColorOp.Color, PICATextureCombinerColorOp.Color, PICATextureCombinerColorOp.Color };
                    Material.MaterialParams.TexEnvStages[0].Operand.Alpha     = new PICATextureCombinerAlphaOp[] { PICATextureCombinerAlphaOp.Alpha, PICATextureCombinerAlphaOp.Alpha, PICATextureCombinerAlphaOp.Alpha };
                    Material.MaterialParams.TexEnvStages[0].Combiner.Color    = PICATextureCombinerMode.Modulate;
                    Material.MaterialParams.TexEnvStages[0].Combiner.Alpha    = PICATextureCombinerMode.Replace;
                    Material.MaterialParams.TexEnvStages[0].Color             = RGBA.White;
                    Material.MaterialParams.TexEnvStages[0].Scale.Color       = PICATextureCombinerScale.One;
                    Material.MaterialParams.TexEnvStages[0].Scale.Alpha       = PICATextureCombinerScale.One;
                    Material.MaterialParams.TexEnvStages[0].UpdateColorBuffer = false;
                    Material.MaterialParams.TexEnvStages[0].UpdateAlphaBuffer = false;

                    Material.MaterialParams.TexEnvStages[1].Source.Color      = new PICATextureCombinerSource[] { PICATextureCombinerSource.Previous, PICATextureCombinerSource.FragmentPrimaryColor, PICATextureCombinerSource.Previous };
                    Material.MaterialParams.TexEnvStages[1].Source.Alpha      = new PICATextureCombinerSource[] { PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous };
                    Material.MaterialParams.TexEnvStages[1].Operand.Color     = new PICATextureCombinerColorOp[] { PICATextureCombinerColorOp.Color, PICATextureCombinerColorOp.Color, PICATextureCombinerColorOp.Color };
                    Material.MaterialParams.TexEnvStages[1].Operand.Alpha     = new PICATextureCombinerAlphaOp[] { PICATextureCombinerAlphaOp.Alpha, PICATextureCombinerAlphaOp.Alpha, PICATextureCombinerAlphaOp.Alpha };
                    Material.MaterialParams.TexEnvStages[1].Combiner.Color    = PICATextureCombinerMode.Modulate;
                    Material.MaterialParams.TexEnvStages[1].Combiner.Alpha    = PICATextureCombinerMode.Replace;
                    Material.MaterialParams.TexEnvStages[1].Color             = RGBA.Black;
                    Material.MaterialParams.TexEnvStages[1].Scale.Color       = PICATextureCombinerScale.One;
                    Material.MaterialParams.TexEnvStages[1].Scale.Alpha       = PICATextureCombinerScale.One;
                    Material.MaterialParams.TexEnvStages[1].UpdateColorBuffer = false;
                    Material.MaterialParams.TexEnvStages[1].UpdateAlphaBuffer = false;

                    Material.MaterialParams.TexEnvStages[2].Source.Color      = new PICATextureCombinerSource[] { PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous };
                    Material.MaterialParams.TexEnvStages[2].Source.Alpha      = new PICATextureCombinerSource[] { PICATextureCombinerSource.Previous, PICATextureCombinerSource.PrimaryColor, PICATextureCombinerSource.Previous };
                    Material.MaterialParams.TexEnvStages[2].Operand.Color     = new PICATextureCombinerColorOp[] { PICATextureCombinerColorOp.Color, PICATextureCombinerColorOp.Color, PICATextureCombinerColorOp.Color };
                    Material.MaterialParams.TexEnvStages[2].Operand.Alpha     = new PICATextureCombinerAlphaOp[] { PICATextureCombinerAlphaOp.Alpha, PICATextureCombinerAlphaOp.Alpha, PICATextureCombinerAlphaOp.Alpha };
                    Material.MaterialParams.TexEnvStages[2].Combiner.Color    = PICATextureCombinerMode.Replace;
                    Material.MaterialParams.TexEnvStages[2].Combiner.Alpha    = PICATextureCombinerMode.Modulate;
                    Material.MaterialParams.TexEnvStages[2].Color             = RGBA.White;
                    Material.MaterialParams.TexEnvStages[2].Scale.Color       = PICATextureCombinerScale.One;
                    Material.MaterialParams.TexEnvStages[2].Scale.Alpha       = PICATextureCombinerScale.One;
                    Material.MaterialParams.TexEnvStages[2].UpdateColorBuffer = false;
                    Material.MaterialParams.TexEnvStages[2].UpdateAlphaBuffer = false;

                    Material.MaterialParams.TexEnvStages[3].Source.Color      = new PICATextureCombinerSource[] { PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous };
                    Material.MaterialParams.TexEnvStages[3].Source.Alpha      = new PICATextureCombinerSource[] { PICATextureCombinerSource.Previous, PICATextureCombinerSource.Constant, PICATextureCombinerSource.Previous };
                    Material.MaterialParams.TexEnvStages[3].Operand.Color     = new PICATextureCombinerColorOp[] { PICATextureCombinerColorOp.Color, PICATextureCombinerColorOp.Color, PICATextureCombinerColorOp.Color };
                    Material.MaterialParams.TexEnvStages[3].Operand.Alpha     = new PICATextureCombinerAlphaOp[] { PICATextureCombinerAlphaOp.Alpha, PICATextureCombinerAlphaOp.Alpha, PICATextureCombinerAlphaOp.Alpha };
                    Material.MaterialParams.TexEnvStages[3].Combiner.Color    = PICATextureCombinerMode.Replace;
                    Material.MaterialParams.TexEnvStages[3].Combiner.Alpha    = PICATextureCombinerMode.Modulate;
                    Material.MaterialParams.TexEnvStages[3].Color             = RGBA.White;
                    Material.MaterialParams.TexEnvStages[3].Scale.Color       = PICATextureCombinerScale.One;
                    Material.MaterialParams.TexEnvStages[3].Scale.Alpha       = PICATextureCombinerScale.One;
                    Material.MaterialParams.TexEnvStages[3].UpdateColorBuffer = false;
                    Material.MaterialParams.TexEnvStages[3].UpdateAlphaBuffer = false;

                    Material.MaterialParams.TexEnvStages[4].Source.Color      = new PICATextureCombinerSource[] { PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous };
                    Material.MaterialParams.TexEnvStages[4].Source.Alpha      = new PICATextureCombinerSource[] { PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous };
                    Material.MaterialParams.TexEnvStages[4].Operand.Color     = new PICATextureCombinerColorOp[] { PICATextureCombinerColorOp.Color, PICATextureCombinerColorOp.Color, PICATextureCombinerColorOp.Color };
                    Material.MaterialParams.TexEnvStages[4].Operand.Alpha     = new PICATextureCombinerAlphaOp[] { PICATextureCombinerAlphaOp.Alpha, PICATextureCombinerAlphaOp.Alpha, PICATextureCombinerAlphaOp.Alpha };
                    Material.MaterialParams.TexEnvStages[4].Combiner.Color    = PICATextureCombinerMode.Replace;
                    Material.MaterialParams.TexEnvStages[4].Combiner.Alpha    = PICATextureCombinerMode.Replace;
                    Material.MaterialParams.TexEnvStages[4].Color             = RGBA.Black;
                    Material.MaterialParams.TexEnvStages[4].Scale.Color       = PICATextureCombinerScale.One;
                    Material.MaterialParams.TexEnvStages[4].Scale.Alpha       = PICATextureCombinerScale.One;
                    Material.MaterialParams.TexEnvStages[4].UpdateColorBuffer = true;
                    Material.MaterialParams.TexEnvStages[4].UpdateAlphaBuffer = false;

                    Material.MaterialParams.TexEnvStages[5].Source.Color      = new PICATextureCombinerSource[] { PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous };
                    Material.MaterialParams.TexEnvStages[5].Source.Alpha      = new PICATextureCombinerSource[] { PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous, PICATextureCombinerSource.Previous };
                    Material.MaterialParams.TexEnvStages[5].Operand.Color     = new PICATextureCombinerColorOp[] { PICATextureCombinerColorOp.Color, PICATextureCombinerColorOp.Color, PICATextureCombinerColorOp.Color };
                    Material.MaterialParams.TexEnvStages[5].Operand.Alpha     = new PICATextureCombinerAlphaOp[] { PICATextureCombinerAlphaOp.Alpha, PICATextureCombinerAlphaOp.Alpha, PICATextureCombinerAlphaOp.Alpha };
                    Material.MaterialParams.TexEnvStages[5].Combiner.Color    = PICATextureCombinerMode.Replace;
                    Material.MaterialParams.TexEnvStages[5].Combiner.Alpha    = PICATextureCombinerMode.Replace;
                    Material.MaterialParams.TexEnvStages[5].Color             = RGBA.Black;
                    Material.MaterialParams.TexEnvStages[5].Scale.Color       = PICATextureCombinerScale.One;
                    Material.MaterialParams.TexEnvStages[5].Scale.Alpha       = PICATextureCombinerScale.One;
                    Material.MaterialParams.TexEnvStages[5].UpdateColorBuffer = false;
                    Material.MaterialParams.TexEnvStages[5].UpdateAlphaBuffer = false;

                    if (Mesh.Name.Contains("alpha"))
                    {
                        if (Mesh.Name.Contains("alphablend"))
                        {
                            M.Layer = 1;
                            Material.MaterialParams.ColorOperation.BlendMode    = PICABlendMode.Blend;
                            Material.MaterialParams.BlendFunction.ColorDstFunc  = PICABlendFunc.OneMinusSourceAlpha;
                            Material.MaterialParams.BlendFunction.ColorEquation = PICABlendEquation.FuncAdd;
                            Material.MaterialParams.BlendFunction.ColorSrcFunc  = PICABlendFunc.SourceAlpha;
                            Material.MaterialParams.BlendFunction.AlphaDstFunc  = PICABlendFunc.OneMinusSourceAlpha;
                            Material.MaterialParams.BlendFunction.AlphaEquation = PICABlendEquation.FuncAdd;
                            Material.MaterialParams.BlendFunction.AlphaSrcFunc  = PICABlendFunc.SourceAlpha;
                            if (Mesh.Name.Contains("rl"))
                            {
                                int digit = Mesh.Name[Mesh.Name.IndexOf("rl") + 2] - '0';
                                if (digit >= 0 && digit <= 3)
                                {
                                    //set renderlayer
                                    M.Priority = digit;
                                }
                            }
                        }
                        Material.MaterialParams.AlphaTest.Enabled   = true;
                        Material.MaterialParams.AlphaTest.Function  = PICATestFunc.Greater;
                        Material.MaterialParams.AlphaTest.Reference = 0;
                    }

                    if (Mesh.Name.Contains("unculled"))
                    {
                        Material.MaterialParams.FaceCulling = PICAFaceCulling.Never;
                    }

                    if (Material.Name.Contains("mado") || Material.Name.Contains("window"))
                    {
                        Material.MaterialParams.LightSetIndex = 1;
                    }

                    Material.TextureMappers[0].MagFilter = H3DTextureMagFilter.Linear;

                    if (Model.Materials.Find(Material.Name) != -1)
                    {
                        M.MaterialIndex = (ushort)Model.Materials.Find(Material.Name);

                        MaterialIndex--;

                        M.UpdateBoolUniforms(Model.Materials[M.MaterialIndex]);
                    }
                    else
                    {
                        Model.Materials.Add(Material);

                        M.UpdateBoolUniforms(Material);
                    }

                    Model.AddMesh(M);
                }


                /*
                 * On Pokémon, the root bone (on the animaiton file) is used by the game to move
                 * characters around, and all rigged bones are parented to this bone.
                 * It's usually the Waist bone, that points upward and is half the character height.
                 */
                /*Model.Skeleton.Add(new H3DBone(
                 *  new Vector3(0, Height * 0.5f, 0),
                 *  new Vector3(0, 0, (float)(Math.PI * 0.5)),
                 *  Vector3.One,
                 *  "Waist",
                 *  -1));*/

                //Model.Skeleton[0].CalculateTransform(Model.Skeleton);

                Output.Models.Add(Model);

                Output.CopyMaterials();
            }

            return(Output);
        }
Ejemplo n.º 8
0
        public static PICAVertex[] GetVertices(DICTObjShape shape, int vertexBufferIndex)
        {
            if (!(shape.VertexBuffers[vertexBufferIndex] is VertexBufferInterleaved))
            {
                throw new InvalidOperationException($"Currently only supports VertexBufferInterleaved, but this is a {shape.VertexBuffers[vertexBufferIndex].GetType().Name}");
            }

            var vertexBuffer = (VertexBufferInterleaved)shape.VertexBuffers[vertexBufferIndex];

            if (vertexBuffer.RawBuffer.Length == 0)
            {
                return(new PICAVertex[0]);
            }

            float[] Elems = new float[4];

            PICAVertex[] Output = new PICAVertex[vertexBuffer.RawBuffer.Length / vertexBuffer.VertexStride];

            using (MemoryStream MS = new MemoryStream(vertexBuffer.RawBuffer))
            {
                BinaryReader Reader = new BinaryReader(MS);

                for (int Index = 0; Index < Output.Length; Index++)
                {
                    PICAVertex Out = new PICAVertex();

                    MS.Seek(Index * vertexBuffer.VertexStride, SeekOrigin.Begin);

                    int bi = 0;
                    int wi = 0;

                    foreach (PICAAttribute Attrib in vertexBuffer.Attributes.Select(a => PICAAttribute.GetPICAAttribute(a)))
                    {
                        AlignStream(MS, Attrib.Format);

                        for (int Elem = 0; Elem < Attrib.Elements; Elem++)
                        {
                            switch (Attrib.Format)
                            {
                            case PICAAttributeFormat.Byte: Elems[Elem] = Reader.ReadSByte(); break;

                            case PICAAttributeFormat.Ubyte: Elems[Elem] = Reader.ReadByte(); break;

                            case PICAAttributeFormat.Short: Elems[Elem] = Reader.ReadInt16(); break;

                            case PICAAttributeFormat.Float: Elems[Elem] = Reader.ReadSingle(); break;
                            }
                        }

                        Vector4 v = new Vector4(Elems[0], Elems[1], Elems[2], Elems[3]);

                        v *= Attrib.Scale;

                        if (Attrib.Name == VertexBuffer.PICAAttributeName.Position)
                        {
                            v.X += shape.PositionOffset.X;
                            v.Y += shape.PositionOffset.Y;
                            v.Z += shape.PositionOffset.Z;
                        }

                        switch (Attrib.Name)
                        {
                        case VertexBuffer.PICAAttributeName.Position: Out.Position = v; break;

                        case VertexBuffer.PICAAttributeName.Normal: Out.Normal = v; break;

                        case VertexBuffer.PICAAttributeName.Tangent: Out.Tangent = v; break;

                        case VertexBuffer.PICAAttributeName.Color: Out.Color = v; break;

                        case VertexBuffer.PICAAttributeName.TexCoord0: Out.TexCoord0 = v; break;

                        case VertexBuffer.PICAAttributeName.TexCoord1: Out.TexCoord1 = v; break;

                        case VertexBuffer.PICAAttributeName.TexCoord2: Out.TexCoord2 = v; break;

                        case VertexBuffer.PICAAttributeName.BoneIndex:
                            Out.Indices[bi++] = (int)v.X; if (Attrib.Elements == 1)
                            {
                                break;
                            }
                            Out.Indices[bi++] = (int)v.Y; if (Attrib.Elements == 2)
                            {
                                break;
                            }
                            Out.Indices[bi++] = (int)v.Z; if (Attrib.Elements == 3)
                            {
                                break;
                            }
                            Out.Indices[bi++] = (int)v.W; break;

                        case VertexBuffer.PICAAttributeName.BoneWeight:
                            Out.Weights[wi++] = v.X; if (Attrib.Elements == 1)
                            {
                                break;
                            }
                            Out.Weights[wi++] = v.Y; if (Attrib.Elements == 2)
                            {
                                break;
                            }
                            Out.Weights[wi++] = v.Z; if (Attrib.Elements == 3)
                            {
                                break;
                            }
                            Out.Weights[wi++] = v.W; break;
                        }
                    }

                    // TODO -- missing FixedAttribute support

                    //if (Mesh.FixedAttributes != null)
                    //{
                    //    bool HasFixedIndices = Mesh.FixedAttributes.Any(x => x.Name == VertexBuffer.PICAAttributeName.BoneIndex);
                    //    bool HasFixedWeights = Mesh.FixedAttributes.Any(x => x.Name == VertexBuffer.PICAAttributeName.BoneWeight);

                    //    if (HasFixedIndices || HasFixedWeights)
                    //    {
                    //        foreach (PICAFixedAttribute Attr in Mesh.FixedAttributes)
                    //        {
                    //            switch (Attr.Name)
                    //            {
                    //                case VertexBuffer.PICAAttributeName.BoneIndex:
                    //                    Out.Indices[0] = (int)Attr.Value.X;
                    //                    Out.Indices[1] = (int)Attr.Value.Y;
                    //                    Out.Indices[2] = (int)Attr.Value.Z;
                    //                    break;

                    //                case VertexBuffer.PICAAttributeName.BoneWeight:
                    //                    Out.Weights[0] = Attr.Value.X;
                    //                    Out.Weights[1] = Attr.Value.Y;
                    //                    Out.Weights[2] = Attr.Value.Z;
                    //                    break;
                    //            }
                    //        }
                    //    }
                    //}

                    Output[Index] = Out;
                }
            }

            return(Output);
        }
Ejemplo n.º 9
0
        public H3D ToH3D(string TextureAndMtlSearchPath = null)
        {
            H3D Output = new H3D();

            Dictionary <string, OBJMaterial> Materials = new Dictionary <string, OBJMaterial>();

            if (TextureAndMtlSearchPath != null)
            {
                string MaterialFile = Path.Combine(TextureAndMtlSearchPath, MtlFile);

                if (File.Exists(MaterialFile))
                {
                    string MaterialName = null;

                    OBJMaterial Material = default(OBJMaterial);

                    TextReader Reader = new StreamReader(MaterialFile);

                    for (string Line; (Line = Reader.ReadLine()) != null;)
                    {
                        string[] Params = Line.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);

                        if (Params.Length == 0)
                        {
                            continue;
                        }

                        switch (Params[0])
                        {
                        case "newmtl":
                            if (Params.Length > 1)
                            {
                                if (MaterialName != null && Material.DiffuseTexture != null)
                                {
                                    Materials.Add(MaterialName, Material);
                                }

                                Material = new OBJMaterial();

                                MaterialName = Line.Substring(Line.IndexOf(" ")).Trim();
                            }
                            break;

                        case "map_Kd":
                            if (Params.Length > 1)
                            {
                                string Name = Line.Substring(Line.IndexOf(Params[1]));

                                string TextureFile = Path.Combine(TextureAndMtlSearchPath, Name);
                                string TextureName = Path.GetFileNameWithoutExtension(TextureFile);

                                if (File.Exists(TextureFile) && !Output.Textures.Contains(TextureName))
                                {
                                    Output.Textures.Add(new H3DTexture(TextureFile));
                                }

                                Material.DiffuseTexture = Path.GetFileNameWithoutExtension(TextureName);
                            }
                            break;

                        case "Ka":
                        case "Kd":
                        case "Ks":
                            if (Params.Length >= 4)
                            {
                                Vector4 Color = new Vector4(
                                    float.Parse(Params[1], CultureInfo.InvariantCulture),
                                    float.Parse(Params[2], CultureInfo.InvariantCulture),
                                    float.Parse(Params[3], CultureInfo.InvariantCulture), 1);

                                switch (Params[0])
                                {
                                case "Ka": Material.Ambient = Color; break;

                                case "Kd": Material.Diffuse = Color; break;

                                case "Ks": Material.Specular = Color; break;
                                }
                            }
                            break;
                        }
                    }

                    Reader.Dispose();

                    if (MaterialName != null && Material.DiffuseTexture != null)
                    {
                        Materials.Add(MaterialName, Material);
                    }
                }
            }

            H3DModel Model = new H3DModel();

            Model.Name = "Model";

            ushort MaterialIndex = 0;

            Model.Flags       = H3DModelFlags.HasSkeleton;
            Model.BoneScaling = H3DBoneScaling.Maya;
            Model.MeshNodesVisibility.Add(true);

            float Height = 0;

            foreach (OBJMesh Mesh in Meshes)
            {
                Vector3 MinVector = new Vector3();
                Vector3 MaxVector = new Vector3();

                Dictionary <PICAVertex, int> Vertices = new Dictionary <PICAVertex, int>();

                List <H3DSubMesh> SubMeshes = new List <H3DSubMesh>();

                Queue <PICAVertex> VerticesQueue = new Queue <PICAVertex>();

                foreach (PICAVertex Vertex in Mesh.Vertices)
                {
                    VerticesQueue.Enqueue(Vertex);
                }

                while (VerticesQueue.Count > 2)
                {
                    List <ushort> Indices = new List <ushort>();

                    while (VerticesQueue.Count > 0)
                    {
                        for (int Tri = 0; Tri < 3; Tri++)
                        {
                            PICAVertex Vertex = VerticesQueue.Dequeue();

                            if (Vertices.ContainsKey(Vertex))
                            {
                                Indices.Add((ushort)Vertices[Vertex]);
                            }
                            else
                            {
                                Indices.Add((ushort)Vertices.Count);

                                if (Vertex.Position.X < MinVector.X)
                                {
                                    MinVector.X = Vertex.Position.X;
                                }
                                if (Vertex.Position.Y < MinVector.Y)
                                {
                                    MinVector.Y = Vertex.Position.Y;
                                }
                                if (Vertex.Position.Z < MinVector.Z)
                                {
                                    MinVector.Z = Vertex.Position.Z;
                                }

                                if (Vertex.Position.X > MaxVector.X)
                                {
                                    MaxVector.X = Vertex.Position.X;
                                }
                                if (Vertex.Position.Y > MaxVector.Y)
                                {
                                    MaxVector.Y = Vertex.Position.Y;
                                }
                                if (Vertex.Position.Z > MaxVector.Z)
                                {
                                    MaxVector.Z = Vertex.Position.Z;
                                }

                                Vertices.Add(Vertex, Vertices.Count);
                            }
                        }
                    }

                    H3DSubMesh SM = new H3DSubMesh();

                    SM.BoneIndices = new ushort[] { 0 };
                    SM.Skinning    = H3DSubMeshSkinning.Smooth;
                    SM.Indices     = Indices.ToArray();

                    SubMeshes.Add(SM);
                }

                //Mesh
                List <PICAAttribute> Attributes = PICAAttribute.GetAttributes(
                    PICAAttributeName.Position,
                    PICAAttributeName.Normal,
                    PICAAttributeName.TexCoord0,
                    PICAAttributeName.Color,
                    PICAAttributeName.BoneIndex,
                    PICAAttributeName.BoneWeight);

                H3DMesh M = new H3DMesh(Vertices.Keys, Attributes, SubMeshes)
                {
                    Skinning      = H3DMeshSkinning.Smooth,
                    MeshCenter    = (MinVector + MaxVector) * 0.5f,
                    MaterialIndex = MaterialIndex
                };

                if (Height < MaxVector.Y)
                {
                    Height = MaxVector.Y;
                }

                //Material
                string MatName = $"Mat{MaterialIndex++.ToString("D5")}_{Mesh.MaterialName}";

                H3DMaterial Material = H3DMaterial.GetSimpleMaterial(Model.Name, MatName, null);

                if (Materials.ContainsKey(Mesh.MaterialName))
                {
                    Material.Texture0Name = Materials[Mesh.MaterialName].DiffuseTexture;
                }
                else
                {
                    Material.Texture0Name = "NoTexture";
                }

                Model.Materials.Add(Material);

                M.UpdateBoolUniforms(Material);

                Model.AddMesh(M);
            }

            /*
             * On Pokémon, the root bone (on the animaiton file) is used by the game to move
             * characters around, and all rigged bones are parented to this bone.
             * It's usually the Waist bone, that points upward and is half the character height.
             */
            Model.Skeleton.Add(new H3DBone(
                                   new Vector3(0, Height * 0.5f, 0),
                                   new Vector3(0, 0, (float)(Math.PI * 0.5)),
                                   Vector3.One,
                                   "Waist",
                                   -1));

            Model.Skeleton[0].CalculateTransform(Model.Skeleton);

            Output.Models.Add(Model);

            Output.CopyMaterials();

            return(Output);
        }