protected override DataStructures.MapObjects.Map GetFromStream(Stream stream) { var map = new DataStructures.MapObjects.Map(); var br = new BinaryReader(stream); // Only RMF version 2.2 is supported for the moment. var version = Math.Round(br.ReadSingle(), 1); if (Math.Abs(version - 2.2) > 0.01) { throw new ProviderException("Incorrect RMF version number. Expected 2.2, got " + version + "."); } map.Version = (decimal) version; // RMF header test var header = br.ReadFixedLengthString(Encoding.UTF8, 3); if (header != "RMF") { throw new ProviderException("Incorrect RMF header. Expected 'RMF', got '" + header + "'."); } // Visgroups var visgroups = ReadVisgroups(br); map.Visgroups.AddRange(visgroups); // Map Objects map.IDGenerator.Reset(); // So the world will be ID = 1 var worldspawn = ReadWorldSpawn(br, map.Visgroups, map.IDGenerator); map.WorldSpawn = worldspawn; // DOCINFO string check var docinfo = br.ReadFixedLengthString(Encoding.UTF8, 8); if (docinfo != "DOCINFO") { throw new ProviderException("Incorrect RMF format. Expected 'DOCINFO', got '" + docinfo + "'."); } // Cameras br.ReadSingle(); // Appears to be a version number for camera data. Unused. var activeCamera = br.ReadInt32(); var cameras = ReadCameras(br); map.Cameras.AddRange(cameras); if (activeCamera >= 0 && activeCamera < map.Cameras.Count) { map.ActiveCamera = map.Cameras[activeCamera]; } return map; }
private static Bitmap Parse(FileInfo file) { // Sprite file spec taken from the spritegen source in the Half-Life SDK. using (var br = new BinaryReader(file.OpenRead())) { var idst = br.ReadFixedLengthString(Encoding.ASCII, 4); if (idst != "IDSP") return null; var version = br.ReadInt32(); if (version != 2) return null; var type = br.ReadInt32(); var texFormat = br.ReadInt32(); var boundingRadius = br.ReadSingle(); var width = br.ReadInt32(); var height = br.ReadInt32(); var numframes = br.ReadInt32(); var beamlength = br.ReadSingle(); var synctype = br.ReadInt32(); var paletteSize = br.ReadInt16(); var palette = br.ReadBytes(paletteSize * 3); // Only read the first frame. var frametype = br.ReadInt32(); if (frametype != 0) { var num = br.ReadInt32(); var intervals = br.ReadSingleArray(num); } var originX = br.ReadInt32(); var originY = br.ReadInt32(); var framewidth = br.ReadInt32(); var frameheight = br.ReadInt32(); var pixels = br.ReadBytes(framewidth * frameheight); var bitmap = new Bitmap(framewidth, frameheight); for (var y = 0; y < frameheight; y++) { for (var x = 0; x < framewidth; x++) { var idx = pixels[framewidth * y + x] * 3; var a = 255; var r = palette[idx + 0]; var g = palette[idx + 1]; var b = palette[idx + 2]; if (b == 255 && r == 0 && g == 0) a = b = 0; // blue pixels are transparent var col = Color.FromArgb(a, r, g, b); bitmap.SetPixel(x, y, col); } } return bitmap; } }
private static Size GetSize(IFile file) { using (var br = new BinaryReader(file.Open())) { var idst = br.ReadFixedLengthString(Encoding.ASCII, 4); if (idst != "IDSP") return Size.Empty; var version = br.ReadInt32(); if (version != 2) return Size.Empty; var type = (SpriteOrientation) br.ReadInt32(); var texFormat = (SpriteRenderMode) br.ReadInt32(); var boundingRadius = br.ReadSingle(); var width = br.ReadInt32(); var height = br.ReadInt32(); return new Size(width, height); } }
public PakPackage(FileInfo packageFile) { PackageFile = packageFile; Entries = new List<PakEntry>(); // Read the data from the pak using (var br = new BinaryReader(OpenFile(packageFile))) { var sig = br.ReadFixedLengthString(Encoding.ASCII, 4); if (sig != Signature) throw new PackageException("Unknown package signature: Expected '" + Signature + "', got '" + sig + "'."); TreeOffset = br.ReadInt32(); TreeLength = br.ReadInt32(); // Read all the entries from the pak ReadPackageEntries(br); BuildDirectories(); } }
public WadPackage(FileInfo packageFile) { PackageFile = packageFile; Entries = new List<WadEntry>(); // Read the data from the wad using (var br = new BinaryReader(OpenFile(packageFile))) { var sig = br.ReadFixedLengthString(Encoding.ASCII, 4); if (sig != Signature) throw new PackageException("Unknown package signature: Expected '" + Signature + "', got '" + sig + "'."); NumTextures = br.ReadUInt32(); LumpOffset = br.ReadUInt32(); // Read all the entries from the wad ReadTextureEntries(br); SetAdditionalEntryData(br); RemoveInvalidEntries(); BuildDirectories(); } }
private static Path ReadPath(BinaryReader br) { var path = new Path { Name = br.ReadFixedLengthString(Encoding.UTF8, 128), Type = br.ReadFixedLengthString(Encoding.UTF8, 128), Direction = (PathDirection) br.ReadInt32() }; var numNodes = br.ReadInt32(); for (var i = 0; i < numNodes; i++) { var node = ReadPathNode(br); node.Parent = path; path.Nodes.Add(node); } return path; }
private static PathNode ReadPathNode(BinaryReader br) { var node = new PathNode { Position = br.ReadCoordinate(), ID = br.ReadInt32(), Name = br.ReadFixedLengthString(Encoding.UTF8, 128) }; var numProps = br.ReadInt32(); for (var i = 0; i < numProps; i++) { node.Properties.Add(ReadProperty(br)); } return node; }
public static Bitmap GetImage(Stream stream, int maxWidth = 0, int maxHeight = 0) { using (var br = new BinaryReader(stream)) { var header = br.ReadFixedLengthString(Encoding.ASCII, 4); if (header != VtfHeader) throw new ProviderException("Invalid VTF header. Expected '" + VtfHeader + "', got '" + header + "'."); var v1 = br.ReadUInt32(); var v2 = br.ReadUInt32(); var version = v1 + (v2 / 10m); // e.g. 7.3 var headerSize = br.ReadUInt32(); var width = br.ReadUInt16(); var height = br.ReadUInt16(); var flags = (VtfImageFlag) br.ReadUInt32(); var numFrames = br.ReadUInt16(); var firstFrame = br.ReadUInt16(); br.ReadBytes(4); // padding var reflectivity = br.ReadCoordinate(); br.ReadBytes(4); // padding var bumpmapScale = br.ReadSingle(); var highResImageFormat = (VtfImageFormat) br.ReadUInt32(); var mipmapCount = br.ReadByte(); var lowResImageFormat = (VtfImageFormat) br.ReadUInt32(); var lowResWidth = br.ReadByte(); var lowResHeight = br.ReadByte(); ushort depth = 1; uint numResources = 0; if (version >= 7.2m) { depth = br.ReadUInt16(); } if (version >= 7.3m) { br.ReadBytes(3); numResources = br.ReadUInt32(); } var faces = 1; if (flags.HasFlag(VtfImageFlag.Envmap)) { faces = version < 7.5m && firstFrame != 0xFFFF ? 7 : 6; } var imageSize = ComputeImageSize(width, height, depth, mipmapCount, highResImageFormat) * faces * numFrames; var thumbnailSize = lowResImageFormat == VtfImageFormat.None ? 0 : ComputeImageSize(lowResWidth, lowResHeight, 1, lowResImageFormat); var thumbnailPos = headerSize; var dataPos = headerSize + thumbnailSize; for (var i = 0; i < numResources; i++) { var type = br.ReadUInt32(); var data = br.ReadUInt32(); switch (type) { case 0x01: // Low res image thumbnailPos = data; break; case 0x30: // Regular image dataPos = data; break; } } if (lowResImageFormat != VtfImageFormat.None) { br.BaseStream.Position = thumbnailPos; var thumbnail = br.ReadBytes((int) thumbnailSize); //var thumbImage = LoadImage(br, lowResWidth, lowResHeight, lowResImageFormat); //return thumbImage; } var mipNum = 0; if (maxWidth > 0 || maxHeight > 0) mipNum = GetMipToLoad(width, height, maxWidth > 0 ? maxWidth : width, maxHeight > 0 ? maxHeight : height, mipmapCount); for (var frame = 0; frame < numFrames; frame++) { for (var face = 0; face < faces; face++) { for (var slice = 0; slice < depth; slice++) { for (var mip = mipNum; mip < mipmapCount; mip++) { var wid = MipmapResize(width, mip); var hei = MipmapResize(height, mip); var offset = GetImageDataLocation(frame, face, slice, mip, highResImageFormat, width, height, numFrames, faces, depth, mipmapCount); br.BaseStream.Position = offset + dataPos; var img = LoadImage(br, (uint) wid, (uint) hei, highResImageFormat); //img.Save(String.Format(@"D:\Github\sledge\_Resources\VTF\_test_fr{0}_fa{1}_sl{2}_m{3}.png", frame, face, slice, mip)); return img; } } } } return null; } }
private static Face ReadFace(BinaryReader br, IDGenerator generator) { var face = new Face(generator.GetNextFaceID()); var textureName = br.ReadFixedLengthString(Encoding.UTF8, 256); br.ReadBytes(4); // Unused face.Texture.Name = textureName; face.Texture.UAxis = br.ReadCoordinate(); face.Texture.XShift = br.ReadSingleAsDecimal(); face.Texture.VAxis = br.ReadCoordinate(); face.Texture.YShift = br.ReadSingleAsDecimal(); face.Texture.Rotation = br.ReadSingleAsDecimal(); face.Texture.XScale = br.ReadSingleAsDecimal(); face.Texture.YScale = br.ReadSingleAsDecimal(); br.ReadBytes(16); // Unused var numVerts = br.ReadInt32(); for (var i = 0; i < numVerts; i++) { face.Vertices.Add(new Vertex(br.ReadCoordinate(), face)); } face.Plane = br.ReadPlane(); face.UpdateBoundingBox(); return face; }
private static Bitmap Parse(IFile file) { // Sprite file spec taken from the spritegen source in the Half-Life SDK. using (var br = new BinaryReader(file.Open())) { var idst = br.ReadFixedLengthString(Encoding.ASCII, 4); if (idst != "IDSP") return null; var version = br.ReadInt32(); if (version != 2) return null; var type = (SpriteOrientation) br.ReadInt32(); var texFormat = (SpriteRenderMode) br.ReadInt32(); var boundingRadius = br.ReadSingle(); var width = br.ReadInt32(); var height = br.ReadInt32(); var numframes = br.ReadInt32(); var beamlength = br.ReadSingle(); var synctype = br.ReadInt32(); var paletteSize = br.ReadInt16(); var palette = br.ReadBytes(paletteSize * 3); if (paletteSize > 256) paletteSize = 256; // Don't accept anything higher var colours = new Color[256]; for (var i = 0; i < paletteSize; i++) { var r = palette[i * 3 + 0]; var g = palette[i * 3 + 1]; var b = palette[i * 3 + 2]; colours[i] = Color.FromArgb(255, r, g, b); } // Only read the first frame. var frametype = br.ReadInt32(); if (frametype != 0) { var num = br.ReadInt32(); var intervals = br.ReadSingleArray(num); } var originX = br.ReadInt32(); var originY = br.ReadInt32(); var framewidth = br.ReadInt32(); var frameheight = br.ReadInt32(); var pixels = br.ReadBytes(framewidth * frameheight); var bitmap = new Bitmap(framewidth, frameheight, PixelFormat.Format8bppIndexed); // Pre-process the palette var pal = bitmap.Palette; var last = colours[255]; for (var i = 0; i < paletteSize; i++) { var c = colours[i]; if (texFormat == SpriteRenderMode.Additive) { var a = (int) ((c.R + c.G + c.B) / 3f); c = Color.FromArgb(a, c); } else if (texFormat == SpriteRenderMode.IndexAlpha && i < 255) { var a = (int) ((c.R + c.G + c.B) / 3f); c = Color.FromArgb(a, last); } pal.Entries[i] = c; } if (texFormat == SpriteRenderMode.AlphaTest) { pal.Entries[255] = Color.FromArgb(0, 0, 0, 0); } bitmap.Palette = pal; // Set the pixel data var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat); Marshal.Copy(pixels, 0, data.Scan0, data.Width * data.Height); bitmap.UnlockBits(data); return bitmap; } }
public static Size GetSize(Stream stream) { using (var br = new BinaryReader(stream)) { var header = br.ReadFixedLengthString(Encoding.ASCII, 4); if (header != VtfHeader) throw new ProviderException("Invalid VTF header. Expected '" + VtfHeader + "', got '" + header + "'."); var v1 = br.ReadUInt32(); var v2 = br.ReadUInt32(); var version = v1 + (v2 / 10); // e.g. 7.3 var headerSize = br.ReadUInt32(); var width = br.ReadUInt16(); var height = br.ReadUInt16(); return new Size(width, height); } }
private static void LoadSourceMeshData(ModelData modelData, IFile file) { modelData.Meshes = new List<VTXModel>(); // In Source the vertices are saved to the VVD file // The vertex windings are saved in the VTX file var vvd = file.GetRelatedFile("vvd"); var vtx = file.GetRelatedFile("vtx"); if (vvd == null) throw new ProviderException("Unable to locate " + file.NameWithoutExtension + ".vvd"); if (vtx == null) throw new ProviderException("Unable to locate " + file.NameWithoutExtension + ".vtx"); var vertices = new List<VVDPoint>(); using (var fs = vvd.Open()) { using (var vbr = new BinaryReader(fs)) { var magicString = vbr.ReadFixedLengthString(Encoding.UTF8, 4); if (magicString != MagicStringIDSV) { throw new ProviderException("Bad magic number for vertex file. Expected IDSV, got: " + magicString); } var version = vbr.ReadInt32(); if (version != VVDVersionSource) { throw new ProviderException("Bad version number for vertex file. Expected 4, got: " + version); } long checksum = vbr.ReadInt32(); var numLods = vbr.ReadInt32(); var numLodVertices = vbr.ReadIntArray(8); var numFixups = vbr.ReadInt32(); var fixupTableStart = vbr.ReadInt32(); var vertexDataStart = vbr.ReadInt32(); var tangentDataStart = vbr.ReadInt32(); vbr.BaseStream.Position = vertexDataStart; // Read all the vertices from LOD 0 (this should contain the vertices for all LODs) for (var i = 0; i < numLodVertices[0]; i++) { var boneWeights = vbr.ReadSingleArray(3); var bones = vbr.ReadBytes(3); var numBones = vbr.ReadByte(); var position = vbr.ReadCoordinateF(); var normal = vbr.ReadCoordinateF(); var textureS = vbr.ReadSingle(); var textureT = vbr.ReadSingle(); vertices.Add(new VVDPoint(boneWeights, bones, numBones, position, normal, textureS, textureT)); } // Apply the fixup table, this re-orders the indices in reverse LOD order for performance reasons if (numFixups > 0) { vbr.BaseStream.Position = fixupTableStart; var newVerts = new List<VVDPoint>(); for (var i = 0; i < numFixups; i++) { var fuLod = vbr.ReadInt32(); var fuvertid = vbr.ReadInt32(); var funumverts = vbr.ReadInt32(); newVerts.AddRange(vertices.GetRange(fuvertid, funumverts)); } vertices.Clear(); vertices.AddRange(newVerts); } modelData.Vertices = vertices; } } using (var fs = vtx.Open()) { using (var vbr = new BinaryReader(fs)) { var version = vbr.ReadInt32(); // 7 if (version != VTXVersionSource) { throw new ProviderException("Bad version number for vertex file. Expected 7, got: " + version); } var vertCacheSize = vbr.ReadInt32(); var maxBonesPerStrip = vbr.ReadUInt16(); var maxBonesPerTri = vbr.ReadUInt16(); var maxBonesPerVert = vbr.ReadInt32(); long checksum = vbr.ReadInt32(); var numLods = vbr.ReadInt32(); var materialReplacementListOffset = vbr.ReadInt32(); var numBodyParts = vbr.ReadInt32(); var bodyPartOffset = vbr.ReadInt32(); // BODY PARTS long posbp = bodyPartOffset; for (var bp = 0; bp < numBodyParts; bp++) { vbr.BaseStream.Position = posbp; var numModels = vbr.ReadInt32(); var modelOffset = vbr.ReadInt32(); var posmdl = posbp + modelOffset; posbp = vbr.BaseStream.Position; // MODELS for (var mdl = 0; mdl < numModels; mdl++) { vbr.BaseStream.Position = posmdl; var numLod = vbr.ReadInt32(); var lodOffset = vbr.ReadInt32(); var poslod = posmdl + lodOffset; posmdl = vbr.BaseStream.Position; // LODS for (var lod = 0; lod < numLod; lod++) { vbr.BaseStream.Position = poslod; var meshNum = vbr.ReadInt32(); var meshOffset = vbr.ReadInt32(); var switchPoint = vbr.ReadSingle(); var posmesh = poslod + meshOffset; poslod = vbr.BaseStream.Position; // MESHES for (var msh = 0; msh < meshNum; msh++) { vbr.BaseStream.Position = posmesh; var sgNum = vbr.ReadInt32(); var sgOffset = vbr.ReadInt32(); var meshFlags = vbr.ReadByte(); var possg = posmesh + sgOffset; posmesh = vbr.BaseStream.Position; var mesh = new VTXModel(bp, mdl, lod, msh); // STRIP GROUPS for (var sg = 0; sg < sgNum; sg++) { vbr.BaseStream.Position = possg; var vertNum = vbr.ReadInt32(); var vertOffset = vbr.ReadInt32(); var indexNum = vbr.ReadInt32(); var indexOffset = vbr.ReadInt32(); var stripNum = vbr.ReadInt32(); var stripOffset = vbr.ReadInt32(); var sgFlags = vbr.ReadByte(); // vbr.ReadIntArray(2); //TODO FIXME Newer model format 49's (DOTA2, CSGO) have two extra integers here, (num + offset, purpose unknown) var posvert = possg + vertOffset; var posidx = possg + indexOffset; var posstrip = possg + stripOffset; possg = vbr.BaseStream.Position; var vertinfo = new List<VTXPoint>(); vbr.BaseStream.Position = posvert; for (var vert = 0; vert < vertNum; vert++) { var boneWeightIndices = vbr.ReadBytes(3); var numBones = vbr.ReadByte(); var meshVertex = vbr.ReadInt16(); var boneIDs = vbr.ReadBytes(3); vertinfo.Add(new VTXPoint(boneWeightIndices, numBones, meshVertex, boneIDs)); } vbr.BaseStream.Position = posidx; var indices = vbr.ReadShortArray(indexNum); // The strips hold info about whether this is a triangle strip or just a list vbr.BaseStream.Position = posstrip; for (var st = 0; st < stripNum; st++) { var numStIndices = vbr.ReadInt32(); var stIndexOffset = vbr.ReadInt32(); var numStVerts = vbr.ReadInt32(); var stVertOffset = vbr.ReadInt32(); var numStBones = vbr.ReadInt16(); var stFlags = vbr.ReadByte(); var numStBoneStateChanges = vbr.ReadInt32(); var stBoneStateChangeOffset = vbr.ReadInt32(); // vbr.ReadIntArray(2); //TODO FIXME Newer model format 49's (DOTA2, CSGO) have two extra integers here, (num + offset, purpose unknown) if ((stFlags & VTXStripGroupTriListFlag) > 0) { for (var j = stIndexOffset; j < stIndexOffset + numStIndices; j++) { mesh.Mesh.Points.Add(vertinfo[indices[j]]); //mesh.Vertices.Add(vertices[vertinfo[indices[j]]]); } } else if ((stFlags & VTXStripGroupTriStripFlag) > 0) { for (var j = stIndexOffset; j < stIndexOffset + numStIndices - 2; j++) { var add = j % 2 == 1 ? new[] { j + 1, j, j + 2 } : new[] { j, j + 1, j + 2 }; foreach (var idx in add) { mesh.Mesh.Points.Add(vertinfo[indices[idx]]); //mesh.Vertices.Add(vertices[vertinfo[indices[idx]]]); } } } } // Strips } // Strip Groups modelData.Meshes.Add(mesh); } // Meshes } // LODs } // Models } // Body Parts } // using (var br) } // using (var fs) }
private static DataStructures.Models.Model ReadModel(BinaryReader br, IFile file, ModelLoadItems loadItems) { // int id - Not really an int. This is a magic string, either "IDST" or "IDSQ". var magicString = br.ReadFixedLengthString(Encoding.UTF8, 4); if (magicString != MagicStringIDST && magicString != MagicStringIDSQ) { throw new ProviderException("Bad magic number for model. Expected [IDST,IDSQ], got: " + magicString); } // int version - Half-life 1 models are version 10. var version = br.ReadInt32(); if (version != MDLVersionGoldsource && version != MDLVersionSource2006 && version != MDLVersionSourceEpisode2 && version != MDLVersionSourcePortal && version != MDLVersionSource2007 && version != MDLVersionSource2012) { throw new ProviderException("Bad version number for model. Expected [10,44,45,46,48,49], got: " + version); } var modelData = new ModelData {Version = version}; if (version >= MDLVersionSource2006) { if (loadItems.HasFlag(ModelLoadItems.Meshes)) { // Source vertex and mesh info is stored in flat file structures, preload these separately. LoadSourceMeshData(modelData, file); } } long checksum = 0; if (version >= MDLVersionSource2006) { checksum = br.ReadInt32(); // This is a long in the headers but is only written to the file in 4 bytes. Why? I don't know. } // char name[64] - The name of the model (file path) var path = br.ReadFixedLengthString(Encoding.UTF8, 64); // int length - The size of the model file in bytes var fileSize = br.ReadInt32(); var eyePosition = br.ReadCoordinateF(); var illumPosition = CoordinateF.Zero; if (version >= MDLVersionSource2006) { illumPosition = br.ReadCoordinateF(); } var hullMin = br.ReadCoordinateF(); var hullMax = br.ReadCoordinateF(); var bbMin = br.ReadCoordinateF(); var bbMax = br.ReadCoordinateF(); // int flags - Unknown. var flags = br.ReadInt32(); var numBones = br.ReadInt32(); var boneIndex = br.ReadInt32(); var numBoneControllers = br.ReadInt32(); var boneControllerIndex = br.ReadInt32(); var numHitBoxes = br.ReadInt32(); var hitboxIndex = br.ReadInt32(); if (version >= MDLVersionSource2006) { var numAnim = br.ReadInt32(); var animIndex = br.ReadInt32(); if (loadItems.HasFlag(ModelLoadItems.Animations)) { // Source animation data is stored on their own instead of inside the sequence LoadSourceAnimationData(br, modelData, numAnim, animIndex); } } var numSeq = br.ReadInt32(); var seqIndex = br.ReadInt32(); int numSeqGroups = 0, seqGroupIndex = 0, activitylistversion = 0, eventsindexed = 0; if (version >= MDLVersionSource2006) { activitylistversion = br.ReadInt32(); eventsindexed = br.ReadInt32(); } else if (version == MDLVersionGoldsource) { numSeqGroups = br.ReadInt32(); seqGroupIndex = br.ReadInt32(); } var numTextures = br.ReadInt32(); var textureIndex = br.ReadInt32(); var textureDataIndex = 0; if (version == MDLVersionGoldsource) { textureDataIndex = br.ReadInt32(); } if (version >= MDLVersionSource2006) { var numcdtextures = br.ReadInt32(); var cdtextureindex = br.ReadInt32(); } var numSkinRef = br.ReadInt32(); var numSkinFamilies = br.ReadInt32(); var skinIndex = br.ReadInt32(); var numBodyParts = br.ReadInt32(); var bodyPartIndex = br.ReadInt32(); var numAttachments = br.ReadInt32(); var attachmentIndex = br.ReadInt32(); if (version >= MDLVersionSource2006) { var numlocalnodes = br.ReadInt32(); var localnodeindex = br.ReadInt32(); var localnodenameindex = br.ReadInt32(); var numflexdesc = br.ReadInt32(); var flexdescindex = br.ReadInt32(); var numflexcontrollers = br.ReadInt32(); var flexcontrollerindex = br.ReadInt32(); var numflexrules = br.ReadInt32(); var flexruleindex = br.ReadInt32(); var numikchains = br.ReadInt32(); var ikchainindex = br.ReadInt32(); var nummouths = br.ReadInt32(); var mouthindex = br.ReadInt32(); var numlocalposeparameters = br.ReadInt32(); var localposeparamindex = br.ReadInt32(); var surfacepropindex = br.ReadInt32(); var keyvalueindex = br.ReadInt32(); var keyvaluesize = br.ReadInt32(); var numlocalikautoplaylocks = br.ReadInt32(); var localikautoplaylockindex = br.ReadInt32(); var mass = br.ReadSingle(); var contents = br.ReadInt32(); var numincludemodels = br.ReadInt32(); var includemodelindex = br.ReadInt32(); var virtualModelPointer = br.ReadInt32(); var szanimblocknameindex = br.ReadInt32(); var numanimblocks = br.ReadInt32(); var animblockindex = br.ReadInt32(); var animblockModelPointer = br.ReadInt32(); var bonetablebynameindex = br.ReadInt32(); var pVertexBasePointer = br.ReadInt32(); var pIndexBasePointer = br.ReadInt32(); var constdirectionallightdot = br.ReadByte(); var rootLod = br.ReadByte(); var numAllowedRootLods = br.ReadByte(); // Unused in Source2006 br.ReadByte(); // Unused var zeroframecacheindex = br.ReadInt32(); // Unused in Source2007 if (version == MDLVersionSource2006) { br.ReadBytes(6); // Unused } else if (version == MDLVersionSource2007) { var numflexcontrollerui = br.ReadInt32(); var flexcontrolleruiindex = br.ReadInt32(); br.ReadIntArray(2); // Unused var studiohdr2Index = br.ReadInt32(); br.ReadInt32(); // Unused } } else if (version == MDLVersionGoldsource) { var soundTable = br.ReadInt32(); var soundIndex = br.ReadInt32(); var soundGroups = br.ReadInt32(); var soundGroupIndex = br.ReadInt32(); var numTransitions = br.ReadInt32(); var transitionIndex = br.ReadInt32(); } var model = new DataStructures.Models.Model(); model.Name = file.NameWithoutExtension; model.BonesTransformMesh = modelData.Version == MDLVersionGoldsource; if (loadItems.HasFlag(ModelLoadItems.Bones)) { // Bones br.BaseStream.Position = boneIndex; for (var i = 0; i < numBones; i++) ReadBone(br, i, modelData, model); } // Controllers // TODO // Attachments // TODO // Hitboxes // TODO if (loadItems.HasFlag(ModelLoadItems.Animations)) { if (version >= MDLVersionSource2006) { throw new ProviderException("Source animations are currently not supported."); } // Sequence Groups var groups = new List<SequenceGroup>(); br.BaseStream.Position = seqGroupIndex; for (var i = 0; i < numSeqGroups; i++) groups.Add(ReadSequenceGroup(br, modelData)); // Sequences br.BaseStream.Position = seqIndex; for (var i = 0; i < numSeq; i++) ReadSequence(br, i, modelData, model, groups); } // Transitions // TODO if (loadItems.HasFlag(ModelLoadItems.Meshes)) { // Body parts br.BaseStream.Position = bodyPartIndex; for (var i = 0; i < numBodyParts; i++) ReadBodyPart(br, i, modelData, model); } // Texture Info if (loadItems.HasFlag(ModelLoadItems.TextureInfo) || loadItems.HasFlag(ModelLoadItems.TextureData)) { ReadTextureInfo(file, br, modelData, model, numTextures, textureIndex); } // Textures return model; }
private void ReadTextureEntries(BinaryReader br) { var validTypes = Enum.GetValues(typeof (WadEntryType)).OfType<WadEntryType>().Select(x => (byte) x).ToArray(); br.BaseStream.Position = LumpOffset; for (int i = 0; i < NumTextures; i++) { var offset = br.ReadUInt32(); var compressedLength = br.ReadUInt32(); var fullLength = br.ReadUInt32(); var type = br.ReadByte(); var compressionType = br.ReadByte(); br.ReadBytes(2); // struct padding var name = br.ReadFixedLengthString(Encoding.ASCII, 16).ToLowerInvariant(); if (!validTypes.Contains(type)) continue; // Skip unsupported types if (Entries.Any(x => x.Name == name)) continue; // Don't add duplicates Entries.Add(new WadEntry(this, name, (WadEntryType) type, offset, compressionType, compressedLength, fullLength)); } }
private static void ReadBodyPart(BinaryReader br, int bodyPartIndex, ModelData data, DataStructures.Models.Model model) { var startIndex = data.Version == MDLVersionGoldsource ? 0 : br.BaseStream.Position; var name = ""; var nameIndex = 0; if (data.Version >= MDLVersionSource2006) { nameIndex = br.ReadInt32(); var idx = br.BaseStream.Position; br.BaseStream.Position = startIndex + nameIndex; name = br.ReadNullTerminatedString(); br.BaseStream.Position = idx; } else if (data.Version == MDLVersionGoldsource) { name = br.ReadFixedLengthString(Encoding.UTF8, 64); } var numModels = br.ReadInt32(); var baseIndex = br.ReadInt32(); var modelIndex = br.ReadInt32(); var endIndex = br.BaseStream.Position; br.BaseStream.Position = modelIndex + startIndex; for (var i = 0; i < numModels; i++) { ReadStudioModel(br, name, bodyPartIndex, i, data, model); } br.BaseStream.Position = endIndex; }
private static void ReadStudioModel(BinaryReader br, string groupName, int bodyPartIndex, int modelIndex, ModelData data, DataStructures.Models.Model model) { var startModelPos = br.BaseStream.Position; var name = br.ReadFixedLengthString(Encoding.ASCII, 64); var type = br.ReadInt32(); var radius = br.ReadSingle(); var numMesh = br.ReadInt32(); var meshIndex = br.ReadInt32(); var numVerts = br.ReadInt32(); var vertInfoIndex = 0; if (data.Version == MDLVersionGoldsource) { vertInfoIndex = br.ReadInt32(); } var vertIndex = br.ReadInt32(); int numNorms = 0, normInfoIndex = 0, normIndex = 0; if (data.Version == MDLVersionGoldsource) { numNorms = br.ReadInt32(); normInfoIndex = br.ReadInt32(); normIndex = br.ReadInt32(); } else if (data.Version >= MDLVersionSource2006) { var tangentsIndex = br.ReadInt32(); } var numGroups = br.ReadInt32(); // Attachments in source var groupIndex = br.ReadInt32(); // Attachments if (data.Version >= MDLVersionSource2006) { var numEyeballs = br.ReadInt32(); var eyeballIndex = br.ReadInt32(); var vertexDataPointer = br.ReadInt32(); var tangentDataPointer = br.ReadInt32(); br.ReadIntArray(8); // Unused } var endPos = br.BaseStream.Position; if (data.Version == MDLVersionGoldsource) { ReadVerticesGoldSource(br, groupName, modelIndex, model, numVerts, vertInfoIndex, vertIndex, numMesh, meshIndex, numNorms, normInfoIndex, normIndex); } else if (data.Version >= MDLVersionSource2006) { ReadVerticesSource(br, groupName, bodyPartIndex, modelIndex, data, model, numMesh, startModelPos + meshIndex); } br.BaseStream.Position = endPos; }
private static SequenceGroup ReadSequenceGroup(BinaryReader br, ModelData data) { var name = br.ReadFixedLengthString(Encoding.ASCII, 32); var filename = br.ReadFixedLengthString(Encoding.ASCII, 64); var cachepointer = br.ReadInt32(); var groupZeroDataIndex = br.ReadInt32(); return new SequenceGroup { Name = name, FileName = filename, CachePointer = cachepointer, GroupZeroDataIndex = groupZeroDataIndex }; }
private static void ReadSequence(BinaryReader br, int index, ModelData data, DataStructures.Models.Model model, IList<SequenceGroup> groups) { var startReadIndex = br.BaseStream.Position; var name = ""; var fps = 0f; if (data.Version == MDLVersionGoldsource) { name = br.ReadFixedLengthString(Encoding.ASCII, 32); fps = br.ReadSingle(); } else if (data.Version >= MDLVersionSource2006) { var baseIndex = br.ReadInt32(); var labelIndex = br.ReadInt32(); var activityNameIndex = br.ReadInt32(); } var flags = br.ReadInt32(); var activity = br.ReadInt32(); var actweight = br.ReadInt32(); var numevents = br.ReadInt32(); var eventindex = br.ReadInt32(); var numframes = 0; if (data.Version == MDLVersionGoldsource) { numframes = br.ReadInt32(); var numpivots = br.ReadInt32(); var pivotindex = br.ReadInt32(); var motiontype = br.ReadInt32(); var motionbone = br.ReadInt32(); var linearmovement = br.ReadCoordinateF(); var automoveposindex = br.ReadInt32(); var automoveangleindex = br.ReadInt32(); } var bbmin = br.ReadCoordinateF(); var bbmax = br.ReadCoordinateF(); var numblends = br.ReadInt32(); var animindex = br.ReadInt32(); var groupsize = new int[0]; if (data.Version >= MDLVersionSource2006) { var movementindex = br.ReadInt32(); groupsize = br.ReadIntArray(2); } var blendtype = br.ReadIntArray(2); // paramindex in source var blendstart = br.ReadSingleArray(2); // paramstart var blendend = br.ReadSingleArray(2); // paramend var blendparent = br.ReadInt32(); // paramparent var seqgroup = 0; if (data.Version == MDLVersionGoldsource) { seqgroup = br.ReadInt32(); } if (data.Version >= MDLVersionSource2006) { var fadeintime = br.ReadSingle(); var fadeouttime = br.ReadSingle(); } var entrynode = br.ReadInt32(); var exitnode = br.ReadInt32(); var nodeflags = br.ReadInt32(); if (data.Version >= MDLVersionSource2006) { var entryphase = br.ReadSingle(); var exitphase = br.ReadSingle(); var lastframe = br.ReadSingle(); } var nextseq = br.ReadInt32(); if (data.Version >= MDLVersionSource2006) { var pose = br.ReadInt32(); var numikrules = br.ReadInt32(); var numautolayers = br.ReadInt32(); var autolayerindex = br.ReadInt32(); var weightlistindex = br.ReadInt32(); var wlpos = br.BaseStream.Position; br.BaseStream.Position = startReadIndex + weightlistindex; var weightList = br.ReadSingleArray(model.Bones.Count); br.BaseStream.Position = wlpos; var posekeyindex = br.ReadInt32(); var numiklocks = br.ReadInt32(); var iklockindex = br.ReadInt32(); var keyvalueindex = br.ReadInt32(); var keyvaluesize = br.ReadInt32(); var cycleposeindex = br.ReadInt32(); br.ReadIntArray(7); // Unused } // Load animtion values var pos = br.BaseStream.Position; if (data.Version == MDLVersionGoldsource) { if (seqgroup > 0) { //TODO: load animations from other files return; // sub out br for another br against the new SG file // br = new BinaryReader(file....etc) // br.BaseStream.Position = animindex; } br.BaseStream.Position = groups[seqgroup].GroupZeroDataIndex + animindex; ReadAnimationGoldsource(br, model, numframes); } else if (data.Version >= MDLVersionSource2006) { br.BaseStream.Position = startReadIndex + animindex; ReadAnimationSource(br, data, model, groupsize); } br.BaseStream.Position = pos; }
private static IEnumerable<Visgroup> ReadVisgroups(BinaryReader br) { var numVisgroups = br.ReadInt32(); for (var i = 0; i < numVisgroups; i++) { var vis = new Visgroup { Name = br.ReadFixedLengthString(Encoding.UTF8, 128), Colour = br.ReadRGBAColour(), ID = br.ReadInt32(), Visible = br.ReadBoolean() }; vis.Colour = Color.FromArgb(255, vis.Colour); br.ReadBytes(3); yield return vis; } }
private static IEnumerable<Visgroup> ReadVisgroups(BinaryReader br) { var list = new List<Visgroup>(); var numVisgroups = br.ReadInt32(); for (var i = 0; i < numVisgroups; i++) { var vis = new Visgroup { Name = br.ReadFixedLengthString(Encoding.UTF8, 128), Colour = br.ReadRGBAColour(), ID = br.ReadInt32(), Visible = br.ReadBoolean() }; vis.Colour = Color.FromArgb(255, vis.Colour); br.ReadBytes(3); list.Add(vis); } // Get rid of zero groups foreach (var vg in list.Where(x => x.ID == 0)) { vg.ID = list.Max(x => x.ID) + 1; } return list; }
private void ReadPackageEntries(BinaryReader br) { br.BaseStream.Position = TreeOffset; var numEntries = TreeLength / 64; for (int i = 0; i < numEntries; i++) { var path = br.ReadFixedLengthString(Encoding.ASCII, 56).ToLowerInvariant(); var offset = br.ReadInt32(); var length = br.ReadInt32(); Entries.Add(new PakEntry(this, path, offset, length)); } }
private static void ReadBone(BinaryReader br, int index, ModelData data, DataStructures.Models.Model model) { var name = ""; var nameIndex = 0; if (data.Version >= MDLVersionSource2006) { nameIndex = br.ReadInt32(); } else if (data.Version == MDLVersionGoldsource) { name = br.ReadFixedLengthString(Encoding.UTF8, 32); } var parent = br.ReadInt32(); int flags = 0; if (data.Version == MDLVersionGoldsource) { flags = br.ReadInt32(); } var boneController = br.ReadIntArray(6); // 3 pos, 3 rot var defPos = br.ReadCoordinateF(); QuaternionF quat = null; if (data.Version >= MDLVersionSource2006) { // quaternion quat = new QuaternionF(br.ReadCoordinateF(), br.ReadSingle()); } var defAng = br.ReadCoordinateF(); var defPosScale = br.ReadCoordinateF(); var defAngScale = br.ReadCoordinateF(); if (data.Version >= MDLVersionSource2006) { var poseToBone = br.ReadIntArray(12); // 3x4 matrix var qAlignment = new QuaternionF(br.ReadCoordinateF(), br.ReadSingle()); flags = br.ReadInt32(); var proctype = br.ReadInt32(); var procindex = br.ReadInt32(); var physicsbone = br.ReadInt32(); var surfacepropidx = br.ReadInt32(); var contents = br.ReadInt32(); br.ReadIntArray(8); // Unused } var parentBone = parent < 0 ? null : model.Bones[parent]; model.Bones.Add(new Bone(index, parent, parentBone, name, defPos, defAng, defPosScale, defAngScale)); }