Beispiel #1
0
        public bool CanLoad(Stream S, string FileName)
        {
            using (BinaryReader Reader = new BinaryReader(S, Encoding.ASCII, true)) {
                IQMHeader H = Reader.ReadStruct <IQMHeader>();

                if (H.GetMagic() == "INTERQUAKEMODEL" && H.Version == 2)
                {
                    return(true);
                }
            }

            return(false);
        }
Beispiel #2
0
        public FoamModel Load(Stream S, string IQMFile)
        {
            int NumFrames = 0;

            ushort[] FrameData = null;

            Vector3[]         Position     = null;
            Vector2[]         Texcoord     = null;
            Vector3[]         Normal       = null;
            Vector4[]         Tangent      = null;
            IQMBlendIndices[] BlendIndexes = null;
            IQMBlendWeights[] BlendWeights = null;
            FoamColor[]       Color        = null;
            byte[]            Text         = null;
            byte[]            Comment      = null;
            IQMTriangle[]     Triangles    = null;
            IQMMesh[]         Meshes       = null;
            IQMJoint[]        Joints       = null;
            IQMPose[]         Poses        = null;
            IQMAnim[]         Anims        = null;

            FoamVertex3[]  FoamVertices = null;
            FoamBoneInfo[] FoamBoneInfo = null;

            using (BinaryReader Reader = new BinaryReader(S, Encoding.UTF8, true)) {
                IQMHeader Header = Reader.ReadStruct <IQMHeader>();
                NumFrames = (int)Header.num_frames;

                if (Header.GetMagic() != "INTERQUAKEMODEL")
                {
                    throw new Exception("Invalid magic in IQM file");
                }

                if (Header.Version != 2)
                {
                    throw new Exception("Only IQM version 2 supported");
                }

                // Text
                if (Header.ofs_text != 0)
                {
                    Reader.Seek(Header.ofs_text);
                    //Text = Encoding.ASCII.GetString(Reader.ReadBytes((int)Header.num_text)).Split(new char[] { (char)0 });
                    Text = Reader.ReadBytes((int)Header.num_text);
                }

                // Comments
                if (Header.ofs_comment != 0)
                {
                    Reader.Seek(Header.ofs_comment);
                    Comment = Reader.ReadBytes((int)Header.num_comment);
                }

                // Vertex arrays
                Reader.Seek(Header.ofs_vertexarrays);
                IQMVertexArray[] VertArrays = new IQMVertexArray[Header.num_vertexarrays];
                for (int i = 0; i < VertArrays.Length; i++)
                {
                    VertArrays[i] = Reader.ReadStruct <IQMVertexArray>();
                }

                for (int i = 0; i < VertArrays.Length; i++)
                {
                    ref IQMVertexArray VA = ref VertArrays[i];
                    Reader.Seek(VA.offset);

                    switch (VA.type)
                    {
                    case IQMVertexArrayType.IQM_POSITION:
                        if (VA.format != IQMVertexArrayFormat.IQM_FLOAT && VA.size != 3)
                        {
                            throw new NotImplementedException();
                        }

                        Position = Reader.ReadStructArray <Vector3>((uint)(Header.num_vertexes * Marshal.SizeOf <Vector3>()));
                        break;

                    case IQMVertexArrayType.IQM_TEXCOORD:
                        if (VA.format != IQMVertexArrayFormat.IQM_FLOAT && VA.size != 2)
                        {
                            throw new NotImplementedException();
                        }

                        Texcoord = Reader.ReadStructArray <Vector2>((uint)(Header.num_vertexes * Marshal.SizeOf <Vector2>()));
                        break;

                    case IQMVertexArrayType.IQM_NORMAL:
                        if (VA.format != IQMVertexArrayFormat.IQM_FLOAT && VA.size != 3)
                        {
                            throw new NotImplementedException();
                        }

                        Normal = Reader.ReadStructArray <Vector3>((uint)(Header.num_vertexes * Marshal.SizeOf <Vector3>()));
                        break;

                    case IQMVertexArrayType.IQM_TANGENT:
                        if (VA.format != IQMVertexArrayFormat.IQM_FLOAT && VA.size != 4)
                        {
                            throw new NotImplementedException();
                        }

                        Tangent = Reader.ReadStructArray <Vector4>((uint)(Header.num_vertexes * Marshal.SizeOf <Vector4>()));
                        break;

                    case IQMVertexArrayType.IQM_BLENDINDEXES:
                        if (VA.format != IQMVertexArrayFormat.IQM_UBYTE && VA.size != 4)
                        {
                            throw new NotImplementedException();
                        }

                        BlendIndexes = Reader.ReadStructArray <IQMBlendIndices>((uint)(Header.num_vertexes * Marshal.SizeOf <IQMBlendIndices>()));
                        break;

                    case IQMVertexArrayType.IQM_BLENDWEIGHTS:
                        if (VA.format != IQMVertexArrayFormat.IQM_UBYTE && VA.size != 4)
                        {
                            throw new NotImplementedException();
                        }

                        BlendWeights = Reader.ReadStructArray <IQMBlendWeights>((uint)(Header.num_vertexes * Marshal.SizeOf <IQMBlendWeights>()));
                        break;

                    case IQMVertexArrayType.IQM_COLOR:
                        if (VA.format != IQMVertexArrayFormat.IQM_UBYTE && VA.size != 4)
                        {
                            throw new NotImplementedException();
                        }

                        Color = Reader.ReadStructArray <FoamColor>((uint)(Header.num_vertexes * Marshal.SizeOf <FoamColor>()));
                        break;

                    case IQMVertexArrayType.IQM_CUSTOM:
                    default:
                        throw new NotImplementedException();
                    }
                }

                // Triangles
                Reader.Seek(Header.ofs_triangles);
                Triangles = Reader.ReadStructArray <IQMTriangle>((uint)(Header.num_triangles * sizeof(IQMTriangle)));

                // Meshes
                Reader.Seek(Header.ofs_meshes);
                Meshes = Reader.ReadStructArray <IQMMesh>((uint)(Header.num_meshes * sizeof(IQMMesh)));

                // Joints
                Reader.Seek(Header.ofs_joints);
                Joints = Reader.ReadStructArray <IQMJoint>((uint)(Header.num_joints * sizeof(IQMJoint)));

                // Poses
                Reader.Seek(Header.ofs_poses);
                Poses = Reader.ReadStructArray <IQMPose>((uint)(Header.num_poses * sizeof(IQMPose)));

                // Anims
                Reader.Seek(Header.ofs_anims);
                Anims = Reader.ReadStructArray <IQMAnim>((uint)(Header.num_anims * sizeof(IQMAnim)));

                // Frames
                Reader.Seek(Header.ofs_frames);
                FrameData = Reader.ReadStructArray <ushort>((uint)(CountFrameDataLength(NumFrames, Poses) * sizeof(ushort)));

                // Foam vertices
                FoamVertices = new FoamVertex3[Header.num_vertexes];
                for (int i = 0; i < FoamVertices.Length; i++)
                {
                    FoamVertices[i] = BuildVertex(i, Tangent, Normal, Position, Texcoord, Color);
                }

                // Foam bone info
                FoamBoneInfo = new FoamBoneInfo[FoamVertices.Length];
                for (int i = 0; i < FoamBoneInfo.Length; i++)
                {
                    FoamBoneInfo Info = new FoamBoneInfo();

                    if (BlendIndexes != null && BlendWeights != null)
                    {
                        IQMBlendIndices BInd = BlendIndexes[i];
                        IQMBlendWeights BWgt = BlendWeights[i];

                        Info.Bone1 = BInd.BlendIndex1;
                        Info.Bone2 = BInd.BlendIndex2;
                        Info.Bone3 = BInd.BlendIndex3;
                        Info.Bone4 = BInd.BlendIndex4;

                        const float WeightDividend = 255.0f;
                        Info.Weight1 = BWgt.BlendWeight1 / WeightDividend;
                        Info.Weight2 = BWgt.BlendWeight2 / WeightDividend;
                        Info.Weight3 = BWgt.BlendWeight3 / WeightDividend;
                        Info.Weight4 = BWgt.BlendWeight4 / WeightDividend;
                    }

                    FoamBoneInfo[i] = Info;
                }
            }