public bool LoadBspFile(Stream buffer) { BinaryReader reader = new BinaryReader(buffer); // read header string id = Encoding.ASCII.GetString(reader.ReadBytes(4), 0, 4); int version = reader.ReadInt32(); if (id != "IBSP" && id != "VBSP") { return(false); } int nHeaderLumps; if (id == "IBSP") { if (version != 0x2E) { return(false); } nHeaderLumps = 17; } else // if (id == "VBSP") { if (version != 0x14) { return(false); } nHeaderLumps = 64; IsVbsp = true; } BspLump[] lumps = new BspLump[nHeaderLumps]; for (int i = 0; i < lumps.Length; i++) { lumps[i].Offset = reader.ReadInt32(); lumps[i].Length = reader.ReadInt32(); if (IsVbsp) { reader.ReadInt32(); // lump format version reader.ReadInt32(); // lump ident code } } // read brushes int lumpHeaderOffset = IsVbsp ? (int)VBspLumpType.Brushes : (int)IBspLumpType.Brushes; buffer.Position = lumps[lumpHeaderOffset].Offset; int length = lumps[lumpHeaderOffset].Length / Marshal.SizeOf(typeof(BspBrush)); Brushes = new BspBrush[length]; for (int i = 0; i < length; i++) { Brushes[i].FirstSide = reader.ReadInt32(); Brushes[i].NumSides = reader.ReadInt32(); Brushes[i].ShaderNum = reader.ReadInt32(); } // read brush sides lumpHeaderOffset = IsVbsp ? (int)VBspLumpType.BrushSides : (int)IBspLumpType.BrushSides; buffer.Position = lumps[lumpHeaderOffset].Offset; length = lumps[lumpHeaderOffset].Length / Marshal.SizeOf(typeof(BspBrushSide)); BrushSides = new BspBrushSide[length]; for (int i = 0; i < length; i++) { if (IsVbsp) { BrushSides[i].PlaneNum = reader.ReadUInt16(); reader.ReadInt16(); // texinfo BrushSides[i].ShaderNum = reader.ReadInt16(); reader.ReadInt16(); // bevel } else { BrushSides[i].PlaneNum = reader.ReadInt32(); BrushSides[i].ShaderNum = reader.ReadInt32(); } } // read entities Entities = new List <BspEntity>(); buffer.Position = lumps[(int)IBspLumpType.Entities].Offset; length = lumps[(int)IBspLumpType.Entities].Length; byte[] entityBytes = new byte[length]; reader.Read(entityBytes, 0, length); string entityString = Encoding.ASCII.GetString(entityBytes); string[] entityStrings = entityString.Split('\n'); BspEntity bspEntity = null; foreach (string entity in entityStrings) { switch (entity) { case "\0": continue; case "{": bspEntity = new BspEntity(); break; case "}": Entities.Add(bspEntity); break; default: string[] keyValue = entity.Trim('\"').Split(new[] { "\" \"" }, 2, 0); switch (keyValue[0]) { case "classname": bspEntity.ClassName = keyValue[1]; break; case "origin": string[] originStrings = keyValue[1].Split(' '); bspEntity.Origin = new Vector3( float.Parse(originStrings[0], CultureInfo.InvariantCulture), float.Parse(originStrings[1], CultureInfo.InvariantCulture), float.Parse(originStrings[2], CultureInfo.InvariantCulture)); break; default: if (!bspEntity.KeyValues.ContainsKey(keyValue[0])) { if (keyValue.Length == 1) { bspEntity.KeyValues.Add(keyValue[0], string.Empty); } else { bspEntity.KeyValues.Add(keyValue[0], keyValue[1]); } } break; } break; } } // read leaves lumpHeaderOffset = IsVbsp ? (int)VBspLumpType.Leafs : (int)IBspLumpType.Leaves; buffer.Position = lumps[lumpHeaderOffset].Offset; length = lumps[lumpHeaderOffset].Length; length /= IsVbsp ? 32 : Marshal.SizeOf(typeof(BspLeaf)); Leaves = new BspLeaf[length]; for (int i = 0; i < length; i++) { if (IsVbsp) { reader.ReadInt32(); // contents Leaves[i].Cluster = reader.ReadInt16(); Leaves[i].Area = reader.ReadInt16(); //Swap Y and Z; invert Z Leaves[i].Min.X = reader.ReadInt16(); Leaves[i].Min.Z = -reader.ReadInt16(); Leaves[i].Min.Y = reader.ReadInt16(); //Swap Y and Z; invert Z Leaves[i].Max.X = reader.ReadInt16(); Leaves[i].Max.Z = -reader.ReadInt16(); Leaves[i].Max.Y = reader.ReadInt16(); Leaves[i].FirstLeafFace = reader.ReadUInt16(); Leaves[i].NumLeafFaces = reader.ReadUInt16(); Leaves[i].FirstLeafBrush = reader.ReadUInt16(); Leaves[i].NumLeafBrushes = reader.ReadUInt16(); reader.ReadInt16(); // leafWaterDataID //reader.ReadInt16(); // ambientLighting //reader.ReadSByte(); // ambientLighting reader.ReadInt16(); // padding } else { Leaves[i].Cluster = reader.ReadInt32(); Leaves[i].Area = reader.ReadInt32(); //Swap Y and Z; invert Z Leaves[i].Min.X = reader.ReadInt32(); Leaves[i].Min.Z = -reader.ReadInt32(); Leaves[i].Min.Y = reader.ReadInt32(); //Swap Y and Z; invert Z Leaves[i].Max.X = reader.ReadInt32(); Leaves[i].Max.Z = -reader.ReadInt32(); Leaves[i].Max.Y = reader.ReadInt32(); Leaves[i].FirstLeafFace = reader.ReadInt32(); Leaves[i].NumLeafFaces = reader.ReadInt32(); Leaves[i].FirstLeafBrush = reader.ReadInt32(); Leaves[i].NumLeafBrushes = reader.ReadInt32(); } } // read leaf brushes lumpHeaderOffset = IsVbsp ? (int)VBspLumpType.LeafBrushes : (int)IBspLumpType.LeafBrushes; buffer.Position = lumps[lumpHeaderOffset].Offset; length = lumps[lumpHeaderOffset].Length; length /= IsVbsp ? sizeof(short) : sizeof(int); LeafBrushes = new int[length]; for (int i = 0; i < length; i++) { if (IsVbsp) { LeafBrushes[i] = reader.ReadInt16(); } else { LeafBrushes[i] = reader.ReadInt32(); } } // read planes lumpHeaderOffset = IsVbsp ? (int)VBspLumpType.Planes : (int)IBspLumpType.Planes; buffer.Position = lumps[lumpHeaderOffset].Offset; length = lumps[lumpHeaderOffset].Length; length /= IsVbsp ? (Marshal.SizeOf(typeof(BspPlane)) + sizeof(int)) : Marshal.SizeOf(typeof(BspPlane)); Planes = new BspPlane[length]; for (int i = 0; i < length; i++) { Planes[i].Normal.X = reader.ReadSingle(); Planes[i].Normal.Y = reader.ReadSingle(); Planes[i].Normal.Z = reader.ReadSingle(); Planes[i].Distance = reader.ReadSingle(); if (IsVbsp) { reader.ReadInt32(); // type } } if (!IsVbsp) { // read shaders Shaders = new List <BspShader>(); buffer.Position = lumps[(int)IBspLumpType.Shaders].Offset; length = lumps[(int)IBspLumpType.Shaders].Length / (64 + 2 * sizeof(int)); byte[] shaderBytes = new byte[64]; for (int i = 0; i < length; i++) { BspShader shader = new BspShader(); reader.Read(shaderBytes, 0, 64); shader.Shader = Encoding.ASCII.GetString(shaderBytes, 0, Array.IndexOf(shaderBytes, (byte)0)); shader.SurfaceFlags = reader.ReadInt32(); shader.ContentFlags = (ContentFlags)reader.ReadInt32(); Shaders.Add(shader); } } return(true); }
public bool LoadBspFile(Stream buffer) { BinaryReader reader = new BinaryReader(buffer); // read header string id = Encoding.ASCII.GetString(reader.ReadBytes(4), 0, 4); int version = reader.ReadInt32(); if (id != "IBSP" && id != "VBSP") return false; int nHeaderLumps; if (id == "IBSP") { if (version != 0x2E) { return false; } nHeaderLumps = 17; } else// if (id == "VBSP") { if (version != 0x14) { return false; } nHeaderLumps = 64; IsVbsp = true; } BspLump[] lumps = new BspLump[nHeaderLumps]; for (int i = 0; i < lumps.Length; i++) { lumps[i].Offset = reader.ReadInt32(); lumps[i].Length = reader.ReadInt32(); if (IsVbsp) { reader.ReadInt32(); // lump format version reader.ReadInt32(); // lump ident code } } // read brushes int lumpHeaderOffset = IsVbsp ? (int)VBspLumpType.Brushes : (int)IBspLumpType.Brushes; buffer.Position = lumps[lumpHeaderOffset].Offset; int length = lumps[lumpHeaderOffset].Length / Marshal.SizeOf(typeof(BspBrush)); Brushes = new BspBrush[length]; for (int i = 0; i < length; i++) { Brushes[i].FirstSide = reader.ReadInt32(); Brushes[i].NumSides = reader.ReadInt32(); Brushes[i].ShaderNum = reader.ReadInt32(); } // read brush sides lumpHeaderOffset = IsVbsp ? (int)VBspLumpType.BrushSides : (int)IBspLumpType.BrushSides; buffer.Position = lumps[lumpHeaderOffset].Offset; length = lumps[lumpHeaderOffset].Length / Marshal.SizeOf(typeof(BspBrushSide)); BrushSides = new BspBrushSide[length]; for (int i = 0; i < length; i++) { if (IsVbsp) { BrushSides[i].PlaneNum = reader.ReadUInt16(); reader.ReadInt16(); // texinfo BrushSides[i].ShaderNum = reader.ReadInt16(); reader.ReadInt16(); // bevel } else { BrushSides[i].PlaneNum = reader.ReadInt32(); BrushSides[i].ShaderNum = reader.ReadInt32(); } } // read entities Entities = new List<BspEntity>(); buffer.Position = lumps[(int)IBspLumpType.Entities].Offset; length = lumps[(int)IBspLumpType.Entities].Length; byte[] entityBytes = new byte[length]; reader.Read(entityBytes, 0, length); string entityString = Encoding.ASCII.GetString(entityBytes); string[] entityStrings = entityString.Split('\n'); BspEntity bspEntity = null; foreach (string entity in entityStrings) { switch (entity) { case "\0": continue; case "{": bspEntity = new BspEntity(); break; case "}": Entities.Add(bspEntity); break; default: string[] keyValue = entity.Trim('\"').Split(new[] { "\" \"" }, 2, 0); switch (keyValue[0]) { case "classname": bspEntity.ClassName = keyValue[1]; break; case "origin": string[] originStrings = keyValue[1].Split(' '); bspEntity.Origin = new Vector3( float.Parse(originStrings[0], CultureInfo.InvariantCulture), float.Parse(originStrings[1], CultureInfo.InvariantCulture), float.Parse(originStrings[2], CultureInfo.InvariantCulture)); break; default: if (!bspEntity.KeyValues.ContainsKey(keyValue[0])) { if (keyValue.Length == 1) { bspEntity.KeyValues.Add(keyValue[0], ""); } else { bspEntity.KeyValues.Add(keyValue[0], keyValue[1]); } } break; } break; } } // read leaves lumpHeaderOffset = IsVbsp ? (int)VBspLumpType.Leafs : (int)IBspLumpType.Leaves; buffer.Position = lumps[lumpHeaderOffset].Offset; length = lumps[lumpHeaderOffset].Length; length /= IsVbsp ? 32 : Marshal.SizeOf(typeof(BspLeaf)); Leaves = new BspLeaf[length]; for (int i = 0; i < length; i++) { if (IsVbsp) { reader.ReadInt32(); // contents Leaves[i].Cluster = reader.ReadInt16(); Leaves[i].Area = reader.ReadInt16(); //Swap Y and Z; invert Z Leaves[i].Min.X = reader.ReadInt16(); Leaves[i].Min.Z = -reader.ReadInt16(); Leaves[i].Min.Y = reader.ReadInt16(); //Swap Y and Z; invert Z Leaves[i].Max.X = reader.ReadInt16(); Leaves[i].Max.Z = -reader.ReadInt16(); Leaves[i].Max.Y = reader.ReadInt16(); Leaves[i].FirstLeafFace = reader.ReadUInt16(); Leaves[i].NumLeafFaces = reader.ReadUInt16(); Leaves[i].FirstLeafBrush = reader.ReadUInt16(); Leaves[i].NumLeafBrushes = reader.ReadUInt16(); reader.ReadInt16(); // leafWaterDataID //reader.ReadInt16(); // ambientLighting //reader.ReadSByte(); // ambientLighting reader.ReadInt16(); // padding } else { Leaves[i].Cluster = reader.ReadInt32(); Leaves[i].Area = reader.ReadInt32(); //Swap Y and Z; invert Z Leaves[i].Min.X = reader.ReadInt32(); Leaves[i].Min.Z = -reader.ReadInt32(); Leaves[i].Min.Y = reader.ReadInt32(); //Swap Y and Z; invert Z Leaves[i].Max.X = reader.ReadInt32(); Leaves[i].Max.Z = -reader.ReadInt32(); Leaves[i].Max.Y = reader.ReadInt32(); Leaves[i].FirstLeafFace = reader.ReadInt32(); Leaves[i].NumLeafFaces = reader.ReadInt32(); Leaves[i].FirstLeafBrush = reader.ReadInt32(); Leaves[i].NumLeafBrushes = reader.ReadInt32(); } } // read leaf brushes lumpHeaderOffset = IsVbsp ? (int)VBspLumpType.LeafBrushes : (int)IBspLumpType.LeafBrushes; buffer.Position = lumps[lumpHeaderOffset].Offset; length = lumps[lumpHeaderOffset].Length; length /= IsVbsp ? sizeof(short) : sizeof(int); LeafBrushes = new int[length]; for (int i = 0; i < length; i++) { if (IsVbsp) { LeafBrushes[i] = reader.ReadInt16(); } else { LeafBrushes[i] = reader.ReadInt32(); } } // read planes lumpHeaderOffset = IsVbsp ? (int)VBspLumpType.Planes : (int)IBspLumpType.Planes; buffer.Position = lumps[lumpHeaderOffset].Offset; length = lumps[lumpHeaderOffset].Length; length /= IsVbsp ? (Marshal.SizeOf(typeof(BspPlane)) + sizeof(int)) : Marshal.SizeOf(typeof(BspPlane)); Planes = new BspPlane[length]; for (int i = 0; i < length; i++) { Planes[i].Normal.X = reader.ReadSingle(); Planes[i].Normal.Y = reader.ReadSingle(); Planes[i].Normal.Z = reader.ReadSingle(); Planes[i].Distance = reader.ReadSingle(); if (IsVbsp) { reader.ReadInt32(); // type } } if (!IsVbsp) { // read shaders Shaders = new List<BspShader>(); buffer.Position = lumps[(int)IBspLumpType.Shaders].Offset; length = lumps[(int)IBspLumpType.Shaders].Length / (64 + 2 * sizeof(int)); byte[] shaderBytes = new byte[64]; for (int i = 0; i < length; i++) { BspShader shader = new BspShader(); reader.Read(shaderBytes, 0, 64); shader.Shader = Encoding.ASCII.GetString(shaderBytes, 0, Array.IndexOf(shaderBytes, (byte)0)); shader.SurfaceFlags = reader.ReadInt32(); shader.ContentFlags = (ContentFlags)reader.ReadInt32(); Shaders.Add(shader); } } return true; }