Update BSP models

This commit is contained in:
Matt Nadareski
2024-11-17 21:20:50 -05:00
parent ea8630ba8c
commit 077aa3c57e
34 changed files with 1061 additions and 85 deletions

View File

@@ -0,0 +1,28 @@
using System.Runtime.InteropServices;
namespace SabreTools.Models.BSP
{
/// <summary>
/// This lump contains the so-called clipnodes, which build a second
/// BSP tree used only for collision detection.
///
/// This structure is a reduced form of the BSPNODE struct from the
/// nodes lump. Also the BSP tree built by the clipnodes is simpler
/// than the one described by the BSPNODEs to accelerate collision calculations.
/// </summary>
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class Clipnode
{
/// <summary>
/// Index into planes
/// </summary>
public int PlaneIndex;
/// <summary>
/// Negative numbers are contents
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public short[]? ChildrenIndices = new short[2];
}
}

View File

@@ -0,0 +1,19 @@
namespace SabreTools.Models.BSP
{
/// <summary>
/// This lump contains the so-called clipnodes, which build a second
/// BSP tree used only for collision detection.
///
/// This structure is a reduced form of the BSPNODE struct from the
/// nodes lump. Also the BSP tree built by the clipnodes is simpler
/// than the one described by the BSPNODEs to accelerate collision calculations.
/// </summary>
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
public sealed class ClipnodesLump : Lump
{
/// <summary>
/// Clipnodes
/// </summary>
public Clipnode[]? Clipnodes { get; set; }
}
}

View File

@@ -1,25 +1,59 @@
namespace SabreTools.Models.BSP
{
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
public static class Constants
{
#region Header
/// <summary>
/// Number of lumps in a BSP
/// </summary>
public const int HL_BSP_LUMP_COUNT = 15;
public const int HEADER_LUMPS = 15;
/// <summary>
/// Index for the entities lump
/// </summary>
public const int HL_BSP_LUMP_ENTITIES = 0;
#endregion
/// <summary>
/// Index for the texture data lump
/// </summary>
public const int HL_BSP_LUMP_TEXTUREDATA = 2;
#region Lump
/// <summary>
/// Number of valid mipmap levels
/// </summary>
public const int HL_BSP_MIPMAP_COUNT = 4;
public const int MAX_MAP_HULLS = 4;
public const int MAX_MAP_MODELS = 400;
public const int MAX_MAP_BRUSHES = 4096;
public const int MAX_MAP_ENTITIES = 1024;
public const int MAX_MAP_ENTSTRING = (128 * 1024);
public const int MAX_MAP_PLANES = 32767;
public const int MAX_MAP_NODES = 32767;
public const int MAX_MAP_CLIPNODES = 32767;
public const int MAX_MAP_LEAFS = 8192;
public const int MAX_MAP_VERTS = 65535;
public const int MAX_MAP_FACES = 65535;
public const int MAX_MAP_MARKSURFACES = 65535;
public const int MAX_MAP_TEXINFO = 8192;
public const int MAX_MAP_EDGES = 256000;
public const int MAX_MAP_SURFEDGES = 512000;
public const int MAX_MAP_TEXTURES = 512;
public const int MAX_MAP_MIPTEX = 0x200000;
public const int MAX_MAP_LIGHTING = 0x200000;
public const int MAX_MAP_VISIBILITY = 0x200000;
public const int MAX_MAP_PORTALS = 65536;
#endregion
#region Entities
public const int MAX_KEY = 32;
public const int MAX_VALUE = 1024;
#endregion
#region Textures
public const int MAXTEXTURENAME = 16;
public const int MIPLEVELS = 4;
#endregion
}
}

View File

@@ -0,0 +1,19 @@
using System.Runtime.InteropServices;
namespace SabreTools.Models.BSP
{
/// <summary>
/// The edges delimit the face and further refer to the vertices of the
/// face. Each edge is pointing to the start and end vertex of the edge.
/// </summary>
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class Edge
{
/// <summary>
/// Indices into vertex array
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public ushort[]? VertexIndices = new ushort[2];
}
}

View File

@@ -0,0 +1,15 @@
namespace SabreTools.Models.BSP
{
/// <summary>
/// The edges delimit the face and further refer to the vertices of the
/// face. Each edge is pointing to the start and end vertex of the edge.
/// </summary>
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
public sealed class EdgesLump : Lump
{
/// <summary>
/// Edge
/// </summary>
public Edge[]? Edges { get; set; }
}
}

View File

@@ -0,0 +1,27 @@
using System.Collections.Generic;
namespace SabreTools.Models.BSP
{
/// <summary>
/// The entity lump is basically a pure ASCII text section.
/// It consists of the string representations of all entities,
/// which are copied directly from the input file to the output
/// BSP file by the compiler.
///
/// Every entity begins and ends with curly brackets. In between
/// there are the attributes of the entity, one in each line,
/// which are pairs of strings enclosed by quotes. The first
/// string is the name of the attribute (the key), the second one
/// its value. The attribute "classname" is mandatory for every
/// entity specifiying its type and therefore, how it is
/// interpreted by the engine.
/// </summary>
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
public sealed class Entity
{
/// <summary>
/// Entity attributes
/// </summary>
public List<KeyValuePair<string, string>>? Attributes { get; set; }
}
}

View File

@@ -0,0 +1,25 @@
namespace SabreTools.Models.BSP
{
/// <summary>
/// The entity lump is basically a pure ASCII text section.
/// It consists of the string representations of all entities,
/// which are copied directly from the input file to the output
/// BSP file by the compiler.
///
/// Every entity begins and ends with curly brackets. In between
/// there are the attributes of the entity, one in each line,
/// which are pairs of strings enclosed by quotes. The first
/// string is the name of the attribute (the key), the second one
/// its value. The attribute "classname" is mandatory for every
/// entity specifiying its type and therefore, how it is
/// interpreted by the engine.
/// </summary>
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
public sealed class EntityLump : Lump
{
/// <summary>
/// Entities
/// </summary>
public Entity[]? Entities { get; set; }
}
}

View File

@@ -0,0 +1,160 @@
using System;
namespace SabreTools.Models.BSP
{
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
public enum Contents : int
{
CONTENTS_EMPTY = -1,
CONTENTS_SOLID = -2,
CONTENTS_WATER = -3,
CONTENTS_SLIME = -4,
CONTENTS_LAVA = -5,
CONTENTS_SKY = -6,
CONTENTS_ORIGIN = -7,
CONTENTS_CLIP = -8,
CONTENTS_CURRENT_0 = -9,
CONTENTS_CURRENT_90 = -10,
CONTENTS_CURRENT_180 = -11,
CONTENTS_CURRENT_270 = -12,
CONTENTS_CURRENT_UP = -13,
CONTENTS_CURRENT_DOWN = -14,
CONTENTS_TRANSLUCENT = -15,
}
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
public enum LumpType : int
{
/// <summary>
/// The entity lump is basically a pure ASCII text section.
/// It consists of the string representations of all entities,
/// which are copied directly from the input file to the output
/// BSP file by the compiler.
/// </summary>
LUMP_ENTITIES = 0,
/// <summary>
/// This lump is a simple array of binary data structures.
/// Each of this structures defines a plane in 3-dimensional
/// space by using the Hesse normal form
/// </summary>
LUMP_PLANES = 1,
/// <summary>
/// The texture lump is somehow a bit more complex then the
/// other lumps, because it is possible to save textures
/// directly within the BSP file instead of storing them in
/// external WAD files.
/// </summary>
LUMP_TEXTURES = 2,
/// <summary>
/// This lump simply consists of all vertices of the BSP tree.
/// They are stored as a primitve array of triples of floats.
/// </summary>
LUMP_VERTICES = 3,
/// <summary>
/// The VIS lump contains data, which is irrelevant to the actual
/// BSP tree, but offers a way to boost up the speed of the
/// renderer significantly. Especially complex maps profit from
/// the use if this data. This lump contains the so-called
/// Potentially Visible Sets (PVS) (also called VIS lists) in the
/// same amout of leaves of the tree, the user can enter (often
/// referred to as VisLeaves). The visiblilty lists are stored as
/// sequences of bitfields, which are run-length encoded.
/// </summary>
LUMP_VISIBILITY = 4,
/// <summary>
/// This lump is simple again and contains an array of binary
/// structures, the nodes, which are a major part of the BSP tree.
/// </summary>
LUMP_NODES = 5,
/// <summary>
/// The texinfo lump contains informations about how textures are
/// applied to surfaces. The lump itself is an array of binary data
/// structures.
/// </summary>
LUMP_TEXINFO = 6,
/// <summary>
/// The face lump contains the surfaces of the scene.
/// </summary>
LUMP_FACES = 7,
/// <summary>
/// This is one of the largest lumps in the BSP file. The lightmap
/// lump stores all lightmaps used in the entire map. The lightmaps
/// are arrays of triples of bytes (3 channel color, RGB) and stored
/// continuously.
/// </summary>
LUMP_LIGHTING = 8,
/// <summary>
/// This lump contains the so-called clipnodes, which build a second
/// BSP tree used only for collision detection.
/// </summary>
LUMP_CLIPNODES = 9,
/// <summary>
/// The leaves lump contains the leaves of the BSP tree.
/// </summary>
LUMP_LEAVES = 10,
/// <summary>
/// The marksurfaces lump is a simple array of short integers.
/// </summary>
LUMP_MARKSURFACES = 11,
/// <summary>
/// The edges delimit the face and further refer to the vertices of the
/// face. Each edge is pointing to the start and end vertex of the edge.
/// </summary>
LUMP_EDGES = 12,
/// <summary>
/// This lump represents pretty much the same mechanism as the marksurfaces.
/// A face can insert its surfedge indexes into this array to get the
/// corresponding edges delimitting the face and further pointing to the
/// vertexes, which are required for rendering. The index can be positive
/// or negative. If the value of the surfedge is positive, the first vertex
/// of the edge is used as vertex for rendering the face, otherwise, the
/// value is multiplied by -1 and the second vertex of the indexed edge is
/// used.
/// </summary>
LUMP_SURFEDGES = 13,
/// <summary>
/// A model is kind of a mini BSP tree. Its size is determinded by the
/// bounding box spaned by the first to members of this struct.
/// </summary>
LUMP_MODELS = 14,
}
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
public enum PlaneType : int
{
// Plane is perpendicular to given axis
PLANE_X = 0,
PLANE_Y = 1,
PLANE_Z = 2,
// Non-axial plane is snapped to the nearest
PLANE_ANYX = 3,
PLANE_ANYY = 4,
PLANE_ANYZ = 5,
}
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
[Flags]
public enum TextureFlag : uint
{
/// <summary>
/// Disable lightmaps and subdivision for the surface
/// </summary>
/// <remarks>Used by sky and liquids</remarks>
DisableLightmaps = 0x01,
}
}

View File

@@ -0,0 +1,66 @@
using System.Runtime.InteropServices;
namespace SabreTools.Models.BSP
{
/// <summary>
/// The face lump contains the surfaces of the scene.
///
/// The first number of this data structure is an index into
/// the planes lump giving a plane which is parallel to this
/// face (meaning they share the same normal). The second
/// value may be seen as a boolean. If nPlaneSide equals 0,
/// then the normal vector of this face equals the one of the
/// parallel plane exactly. Otherwise, the normal of the plane
/// has to be multiplied by -1 to point into the right direction.
/// Afterwards we have an index into the surfedges lump, as
/// well as the count of consecutive surfedges from that position.
/// Furthermore there is an index into the texture info lump,
/// which is used to find the BSPTEXINFO structure needed to
/// calculate the texture coordinates for this face. Afterwards,
/// there are four bytes giving some lighting information (partly
/// used by the renderer to hide sky surfaces). Finally we have
/// an offset in byes giving the beginning of the binary lightmap
/// data of this face in the lighting lump.
/// </summary>
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class Face
{
/// <summary>
/// Plane the face is parallel to
/// </summary>
public ushort PlaneIndex;
/// <summary>
/// Set if different normals orientation
/// </summary>
public ushort PlaneSideCount;
/// <summary>
/// Index of the first surfedge
/// </summary>
public uint FirstEdgeIndex;
/// <summary>
/// Number of consecutive surfedges
/// </summary>
public ushort NumberOfEdges;
/// <summary>
/// Index of the texture info structure
/// </summary>
public ushort TextureInfoIndex;
/// <summary>
/// Specify lighting styles
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[]? LightingStyles = new byte[4];
/// <summary>
/// Offsets into the raw lightmap data; if less than zero,
/// then a lightmap was not baked for the given face.
/// </summary>
public int LightmapOffsetCount;
}
}

View File

@@ -0,0 +1,31 @@
namespace SabreTools.Models.BSP
{
/// <summary>
/// The face lump contains the surfaces of the scene.
///
/// The first number of this data structure is an index into
/// the planes lump giving a plane which is parallel to this
/// face (meaning they share the same normal). The second
/// value may be seen as a boolean. If nPlaneSide equals 0,
/// then the normal vector of this face equals the one of the
/// parallel plane exactly. Otherwise, the normal of the plane
/// has to be multiplied by -1 to point into the right direction.
/// Afterwards we have an index into the surfedges lump, as
/// well as the count of consecutive surfedges from that position.
/// Furthermore there is an index into the texture info lump,
/// which is used to find the BSPTEXINFO structure needed to
/// calculate the texture coordinates for this face. Afterwards,
/// there are four bytes giving some lighting information (partly
/// used by the renderer to hide sky surfaces). Finally we have
/// an offset in byes giving the beginning of the binary lightmap
/// data of this face in the lighting lump.
/// </summary>
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
public sealed class FacesLump : Lump
{
/// <summary>
/// Faces
/// </summary>
public Face[]? Faces { get; set; }
}
}

View File

@@ -4,6 +4,7 @@ namespace SabreTools.Models.BSP
/// Half-Life Level
/// </summary>
/// <see href="https://github.com/RavuAlHemio/hllib/blob/master/HLLib/BSPFile.h"/>
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
public sealed class File
{
/// <summary>
@@ -12,18 +13,9 @@ namespace SabreTools.Models.BSP
public Header? Header { get; set; }
/// <summary>
/// Lumps
/// Lump data
/// </summary>
public Lump?[]? Lumps { get; set; }
/// <summary>
/// Texture header data
/// </summary>
public TextureHeader? TextureHeader { get; set; }
/// <summary>
/// Textures
/// </summary>
public Texture?[]? Textures { get; set; }
/// <remarks>15 entries</remarks>
public Lump[]? Lumps { get; set; } = new Lump[Constants.HEADER_LUMPS];
}
}

View File

@@ -3,12 +3,20 @@ using System.Runtime.InteropServices;
namespace SabreTools.Models.BSP
{
/// <see href="https://github.com/RavuAlHemio/hllib/blob/master/HLLib/BSPFile.h"/>
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class Header
{
/// <summary>
/// Version
/// </summary>
public uint Version;
/// <remarks>Must be 30 for a valid HL BSP file</remarks>
public int Version;
/// <summary>
/// Lumps
/// </summary>
/// <remarks>15 entries</remarks>
public LumpTableEntry[]? Lumps { get; set; }
}
}

View File

@@ -0,0 +1,67 @@
using System.Runtime.InteropServices;
namespace SabreTools.Models.BSP
{
/// <summary>
/// The leaves lump contains the leaves of the BSP tree.
///
/// The first entry of this struct is the type of the content
/// of this leaf. It can be one of the predefined values, found
/// in the compiler source codes, and is litte relevant for the
/// actual rendering process. All the more important is the
/// next integer containing the offset into the vis lump. It
/// defines the start of the raw PVS data for this leaf. If this
/// value equals -1, no VIS lists are available for this leaf,
/// usually if the map has been built without the VIS compiler.
/// The next two 16bit integer triples span the bounding box of
/// this leaf. Furthermore, the struct contains an index pointing
/// into the array of marksurfaces loaded from the marksufaces
/// lump as well as the number of consecutive marksurfaces belonging
/// to this leaf. The marksurfaces are looped through during the
/// rendering process and point to the actual faces. The final 4 bytes
/// specify the volume of ambient sounds in Quake, but are unused in
/// GoldSrc.
/// </summary>
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class Leaf
{
/// <summary>
/// Contents enumeration
/// </summary>
public Contents Contents;
/// <summary>
/// Offset into the visibility lump
/// </summary>
public int VisOffset;
/// <summary>
/// Defines bounding box
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public short[] Mins = new short[3];
/// <summary>
/// Defines bounding box
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public short[] Maxs = new short[3];
/// <summary>
/// Index into marksurfaces array
/// </summary>
public ushort FirstMarkSurfaceIndex;
/// <summary>
/// Count of marksurfaces array
/// </summary>
public ushort MarkSurfacesCount;
/// <summary>
/// Ambient sound levels
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[]? AmbientLevels = new byte[4];
}
}

View File

@@ -0,0 +1,31 @@
namespace SabreTools.Models.BSP
{
/// <summary>
/// The leaves lump contains the leaves of the BSP tree.
///
/// The first entry of this struct is the type of the content
/// of this leaf. It can be one of the predefined values, found
/// in the compiler source codes, and is litte relevant for the
/// actual rendering process. All the more important is the
/// next integer containing the offset into the vis lump. It
/// defines the start of the raw PVS data for this leaf. If this
/// value equals -1, no VIS lists are available for this leaf,
/// usually if the map has been built without the VIS compiler.
/// The next two 16bit integer triples span the bounding box of
/// this leaf. Furthermore, the struct contains an index pointing
/// into the array of marksurfaces loaded from the marksufaces
/// lump as well as the number of consecutive marksurfaces belonging
/// to this leaf. The marksurfaces are looped through during the
/// rendering process and point to the actual faces. The final 4 bytes
/// specify the volume of ambient sounds in Quake, but are unused in
/// GoldSrc.
/// </summary>
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
public sealed class LeavesLump : Lump
{
/// <summary>
/// Leaves
/// </summary>
public Leaf[]? Leaves { get; set; }
}
}

View File

@@ -0,0 +1,18 @@
namespace SabreTools.Models.BSP
{
/// <summary>
/// This is one of the largest lumps in the BSP file. The lightmap
/// lump stores all lightmaps used in the entire map. The lightmaps
/// are arrays of triples of bytes (3 channel color, RGB) and stored
/// continuously.
/// </summary>
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
public sealed class LightmapLump : Lump
{
/// <summary>
/// Lightmap RGB values
/// </summary>
/// <remarks>Array of 3-byte values</remarks>
public byte[,]? Lightmap { get; set; }
}
}

View File

@@ -1,19 +1,11 @@
using System.Runtime.InteropServices;
namespace SabreTools.Models.BSP
{
/// <see href="https://github.com/RavuAlHemio/hllib/blob/master/HLLib/BSPFile.h"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class Lump
/// <summary>
/// Represents a common Lump type
/// </summary>
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
public abstract class Lump
{
/// <summary>
/// Offset
/// </summary>
public uint Offset;
/// <summary>
/// Length
/// </summary>
public uint Length;
// No shared fields between types
}
}

View File

@@ -0,0 +1,20 @@
using System.Runtime.InteropServices;
namespace SabreTools.Models.BSP
{
/// <see href="https://github.com/RavuAlHemio/hllib/blob/master/HLLib/BSPFile.h"/>
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class LumpTableEntry
{
/// <summary>
/// File offset to data
/// </summary>
public int Offset;
/// <summary>
/// Length of data
/// </summary>
public int Length;
}
}

View File

@@ -0,0 +1,19 @@
namespace SabreTools.Models.BSP
{
/// <summary>
/// The marksurfaces lump is a simple array of short integers.
///
/// This lump is a simple table for redirecting the marksurfaces
/// indexes in the leafs to the actial face indexes. A leaf inserts
/// it's marksurface indexes into this array and gets the associated
/// faces contained within this leaf.
/// </summary>
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
public sealed class MarksurfacesLump : Lump
{
/// <summary>
/// Marksurfaces
/// </summary>
public ushort[]? Marksurfaces { get; set; }
}
}

View File

@@ -0,0 +1,44 @@
using System.Runtime.InteropServices;
namespace SabreTools.Models.BSP
{
/// <summary>
/// Each of this structs describes a texture. The name of the
/// texture is a string and may be 16 characters long (including
/// the null-character at the end, char equals a 8bit signed
/// integer). The name of the texture is needed, if the texture
/// has to be found and loaded from an external WAD file.
/// Furthermore, the struct contains the width and height of
/// the texture. The 4 offsets at the end can either be zero,
/// if the texture is stored in an external WAD file, or point
/// to the beginnings of the binary texture data within the
/// texture lump relative to the beginning of it's BSPMIPTEX struct.
/// </summary>
/// <see href="https://github.com/RavuAlHemio/hllib/blob/master/HLLib/BSPFile.h"/>
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class MipTexture
{
/// <summary>
/// Name of texture
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.MAXTEXTURENAME)]
public string? Name;
/// <summary>
/// Extends of the texture
/// </summary>
public uint Width;
/// <summary>
/// Extends of the texture
/// </summary>
public uint Height;
/// <summary>
/// Offsets to texture mipmaps BSPMIPTEX
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.MIPLEVELS)]
public uint[]? Offsets;
}
}

View File

@@ -0,0 +1,65 @@
using System.Runtime.InteropServices;
namespace SabreTools.Models.BSP
{
/// <summary>
/// A model is kind of a mini BSP tree. Its size is determinded
/// by the bounding box spaned by the first to members of this
/// struct. The major difference between a model and the BSP
/// tree holding the scene is that the models use a local
/// coordinate system for their vertexes and just state its
/// origin in world coordinates. During rendering the coordinate
/// system is translated to the origin of the model (glTranslate())
/// and moved back after the models BSP tree has been traversed.
/// Furthermore their are 4 indexes into node arrays. The first
/// one has proofed to index the root node of the mini BSP tree
/// used for rendering. The other three indexes could probably be
/// used for collision detection, meaning they point into the
/// clipnodes, but I am not sure about this. The meaning of the
/// next value is also somehow unclear to me. Finally their are
/// direct indexes into the faces array, not taking the redirecting
/// by the marksurfaces.
/// </summary>
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class Model
{
/// <summary>
/// Defines bounding box
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public float[]? Mins = new float[3];
/// <summary>
/// Defines bounding box
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public float[]? Maxs = new float[3];
/// <summary>
/// Coordinates to move the coordinate system
/// </summary>
public Vector3D OriginVector;
/// <summary>
/// Index into nodes array
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.MAX_MAP_HULLS)]
public int[]? HeadnodesIndex = new int[Constants.MAX_MAP_HULLS];
/// <summary>
/// ???
/// </summary>
public int VisLeafsCount;
/// <summary>
/// Index into faces
/// </summary>
public int FirstFaceIndex;
/// <summary>
/// Count of faces
/// </summary>
public int FacesCount;
}
}

View File

@@ -0,0 +1,29 @@
namespace SabreTools.Models.BSP
{
/// <summary>
/// A model is kind of a mini BSP tree. Its size is determinded
/// by the bounding box spaned by the first to members of this
/// struct. The major difference between a model and the BSP
/// tree holding the scene is that the models use a local
/// coordinate system for their vertexes and just state its
/// origin in world coordinates. During rendering the coordinate
/// system is translated to the origin of the model (glTranslate())
/// and moved back after the models BSP tree has been traversed.
/// Furthermore their are 4 indexes into node arrays. The first
/// one has proofed to index the root node of the mini BSP tree
/// used for rendering. The other three indexes could probably be
/// used for collision detection, meaning they point into the
/// clipnodes, but I am not sure about this. The meaning of the
/// next value is also somehow unclear to me. Finally their are
/// direct indexes into the faces array, not taking the redirecting
/// by the marksurfaces.
/// </summary>
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
public sealed class ModelsLump : Lump
{
/// <summary>
/// Model
/// </summary>
public Model[]? Models { get; set; }
}
}

View File

@@ -0,0 +1,61 @@
using System.Runtime.InteropServices;
namespace SabreTools.Models.BSP
{
/// <summary>
/// This lump is simple again and contains an array of binary
/// structures, the nodes, which are a major part of the BSP tree.
///
/// Every BSPNODE structure represents a node in the BSP tree and
/// every node equals more or less a division step of the BSP algorithm.
/// Therefore, each node has an index (iPlane) referring to a plane
/// in the plane lump which devides the node into its two child nodes.
/// The childnodes are also stored as indexes. Contrary to the plane
/// index, the node index for the child is signed. If the index is
/// larger than 0, the index indicates a child node. If it is equal
/// to or smaller than zero (no valid array index), the bitwise
/// inversed value of the index gives an index into the leaves lump.
/// Additionally two points (nMins, nMaxs) span the bounding box
/// (AABB, axis aligned bounding box) delimitting the space of the node.
/// Finally firstFace indexes into the face lump and spezifies the
/// first of nFaces surfaces contained in this node.
/// </summary>
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class Node
{
/// <summary>
/// Index into Planes lump
/// </summary>
public uint PlaneIndex;
/// <summary>
/// If > 0, then indices into Nodes.
/// Otherwise bitwise inverse indices into Leafs
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public ushort[] Children = new ushort[2];
/// <summary>
/// Defines bounding box
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public ushort[] Mins = new ushort[3];
/// <summary>
/// Defines bounding box
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public ushort[] Maxs = new ushort[3];
/// <summary>
/// Index into Faces
/// </summary>
public ushort FirstFace;
/// <summary>
/// Count of Faces
/// </summary>
public ushort FaceCount;
}
}

View File

@@ -0,0 +1,29 @@
namespace SabreTools.Models.BSP
{
/// <summary>
/// This lump is simple again and contains an array of binary
/// structures, the nodes, which are a major part of the BSP tree.
///
/// Every BSPNODE structure represents a node in the BSP tree and
/// every node equals more or less a division step of the BSP algorithm.
/// Therefore, each node has an index (iPlane) referring to a plane
/// in the plane lump which devides the node into its two child nodes.
/// The childnodes are also stored as indexes. Contrary to the plane
/// index, the node index for the child is signed. If the index is
/// larger than 0, the index indicates a child node. If it is equal
/// to or smaller than zero (no valid array index), the bitwise
/// inversed value of the index gives an index into the leaves lump.
/// Additionally two points (nMins, nMaxs) span the bounding box
/// (AABB, axis aligned bounding box) delimitting the space of the node.
/// Finally firstFace indexes into the face lump and spezifies the
/// first of nFaces surfaces contained in this node.
/// </summary>
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
public sealed class NodesLump : Lump
{
/// <summary>
/// Nodes
/// </summary>
public Node[]? Nodes { get; set; }
}
}

View File

@@ -0,0 +1,39 @@
using System.Runtime.InteropServices;
namespace SabreTools.Models.BSP
{
/// <summary>
/// Each of this structures defines a plane in 3-dimensional
/// space by using the Hesse normal form: normal * point - distance = 0
///
/// Where vNormal is the normalized normal vector of the plane
/// and fDist is the distance of the plane to the origin of
/// the coord system. Additionally, the structure also saves an
/// integer describing the orientation of the plane in space.
/// If nType equals PLANE_X, then the normal of the plane will
/// be parallel to the x axis, meaning the plane is perpendicular
/// to the x axis. If nType equals PLANE_ANYX, then the plane's
/// normal is nearer to the x axis then to any other axis.
/// This information is used by the renderer to speed up some
/// computations.
/// </summary>
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class Plane
{
/// <summary>
/// The planes normal vector
/// </summary>
public Vector3D NormalVector;
/// <summary>
/// Plane equation is: vNormal * X = fDist
/// </summary>
public float Distance;
/// <summary>
/// Plane type
/// </summary>
public PlaneType PlaneType;
}
}

View File

@@ -0,0 +1,15 @@
namespace SabreTools.Models.BSP
{
/// <summary>
/// Each of this structures defines a plane in 3-dimensional
/// space by using the Hesse normal form: normal * point - distance = 0
/// </summary>
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
public sealed class PlaneLump
{
/// <summary>
/// Planes
/// </summary>
public Plane[]? Planes { get; set; }
}
}

View File

@@ -0,0 +1,21 @@
namespace SabreTools.Models.BSP
{
/// <summary>
/// This lump represents pretty much the same mechanism as the marksurfaces.
/// A face can insert its surfedge indexes into this array to get the
/// corresponding edges delimitting the face and further pointing to the
/// vertexes, which are required for rendering. The index can be positive
/// or negative. If the value of the surfedge is positive, the first vertex
/// of the edge is used as vertex for rendering the face, otherwise, the
/// value is multiplied by -1 and the second vertex of the indexed edge is
/// used.
/// </summary>
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
public sealed class SurfedgesLump : Lump
{
/// <summary>
/// Surfedges
/// </summary>
public int[]? Surfedges { get; set; }
}
}

View File

@@ -0,0 +1,52 @@
using System.Runtime.InteropServices;
namespace SabreTools.Models.BSP
{
/// <summary>
/// The texinfo lump contains informations about how textures are
/// applied to surfaces. The lump itself is an array of binary data
/// structures.
///
/// This struct is mainly responsible for the calculation of the texture
/// coordinates (vS, fSShift, vT, fTShift). This values determine the
/// position of the texture on the surface. The iMiptex integer refers
/// to the textures in the texture lump and would be the index in an
/// array of BSPMITEX structs. Finally, there are 4 Bytes used for flags.
/// Only one flag is used by the vanilla engine, being 0x1 for disabling
/// lightmaps and subdivision for the surface (used by sky and liquids).
/// </summary>
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
[StructLayout(LayoutKind.Sequential)]
public sealed class Texinfo
{
/// <summary>
/// S-vector
/// </summary>
public Vector3D SVector;
/// <summary>
/// Texture shift in the S direction
/// </summary>
public float TextureSShift;
/// <summary>
/// T-vector
/// </summary>
public Vector3D TVector;
/// <summary>
/// Texture shift in the T direction
/// </summary>
public float TextureTShift;
/// <summary>
/// Index into textures array
/// </summary>
public uint MiptexIndex;
/// <summary>
/// Texture flags
/// </summary>
public TextureFlag Flags;
}
}

View File

@@ -0,0 +1,24 @@
namespace SabreTools.Models.BSP
{
/// <summary>
/// The texinfo lump contains informations about how textures are
/// applied to surfaces. The lump itself is an array of binary data
/// structures.
///
/// This struct is mainly responsible for the calculation of the texture
/// coordinates (vS, fSShift, vT, fTShift). This values determine the
/// position of the texture on the surface. The iMiptex integer refers
/// to the textures in the texture lump and would be the index in an
/// array of BSPMITEX structs. Finally, there are 4 Bytes used for flags.
/// Only one flag is used by the vanilla engine, being 0x1 for disabling
/// lightmaps and subdivision for the surface (used by sky and liquids).
/// </summary>
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
public sealed class TexinfoLump : Lump
{
/// <summary>
/// Texinfos
/// </summary>
public Texinfo[]? Texinfos { get; set; }
}
}

View File

@@ -1,41 +0,0 @@
namespace SabreTools.Models.BSP
{
/// <see href="https://github.com/RavuAlHemio/hllib/blob/master/HLLib/BSPFile.h"/>
public sealed class Texture
{
/// <summary>
/// Name
/// </summary>
public string? Name { get; set; }
/// <summary>
/// Width
/// </summary>
public uint Width { get; set; }
/// <summary>
/// Height
/// </summary>
public uint Height { get; set; }
/// <summary>
/// Offsets
/// </summary>
public uint[]? Offsets { get; set; }
/// <summary>
/// Texture data
/// </summary>
public byte[]? TextureData { get; set; }
/// <summary>
/// Palette size
/// </summary>
public uint PaletteSize { get; set; }
/// <summary>
/// Palette data
/// </summary>
public byte[]? PaletteData { get; set; }
}
}

View File

@@ -1,17 +1,18 @@
namespace SabreTools.Models.BSP
{
/// <see href="https://github.com/RavuAlHemio/hllib/blob/master/HLLib/BSPFile.h"/>
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
public sealed class TextureHeader
{
/// <summary>
/// Texture count
/// Number of BSPMIPTEX structures
/// </summary>
public uint TextureCount { get; set; }
public uint MipTextureCount { get; set; }
/// <summary>
/// Offsets
/// </summary>
/// <remarks>TextureCount entries</remarks>
public uint[]? Offsets { get; set; }
/// <remarks><see cref="MipTextureCount"> entries</remarks>
public int[]? Offsets { get; set; }
}
}

View File

@@ -0,0 +1,16 @@
namespace SabreTools.Models.BSP
{
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
public sealed class TextureLump : Lump
{
/// <summary>
/// Texture header data
/// </summary>
public TextureHeader? Header { get; set; }
/// <summary>
/// Textures
/// </summary>
public MipTexture[]? Textures { get; set; }
}
}

View File

@@ -0,0 +1,17 @@
using System.Runtime.InteropServices;
namespace SabreTools.Models.BSP
{
/// <summary>
/// There is a common struct used to represent a point in
/// 3-dimensional space which is used throughout the file
/// spec and the code of the hlbsp project.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct Vector3D
{
public float X { get; set; }
public float Y { get; set; }
public float Z { get; set; }
}
}

View File

@@ -0,0 +1,15 @@
namespace SabreTools.Models.BSP
{
/// <summary>
/// This lump simply consists of all vertices of the BSP tree.
/// They are stored as a primitve array of triples of floats.
/// </summary>
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
public sealed class VerticesLump : Lump
{
/// <summary>
/// Vertices
/// </summary>
public Vector3D[]? Vertices { get; set; }
}
}

View File

@@ -0,0 +1,18 @@
namespace SabreTools.Models.BSP
{
/// <summary>
/// The VIS lump contains data, which is irrelevant to the actual
/// BSP tree, but offers a way to boost up the speed of the
/// renderer significantly. Especially complex maps profit from
/// the use if this data. This lump contains the so-called
/// Potentially Visible Sets (PVS) (also called VIS lists) in the
/// same amout of leaves of the tree, the user can enter (often
/// referred to as VisLeaves). The visiblilty lists are stored as
/// sequences of bitfields, which are run-length encoded.
/// </summary>
/// <see href="https://developer.valvesoftware.com/wiki/BSP_(GoldSrc)"/>
public sealed class VisibilityLump
{
public byte[]? Data { get; set; }
}
}