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); }
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; } }