Ejemplo n.º 1
0
        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 Dictionary <string, 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.ClassName, 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);
        }
Ejemplo n.º 2
0
        public void ConvertBsp(BspLoader bspLoader, float scaling)
        {
            Vector3 playerStart = GetPlayerPosition(bspLoader);

            playerStart.Z += 20.0f; //start a bit higher
            playerStart   *= scaling;

            foreach (BspLeaf leaf in bspLoader.Leaves)
            {
                bool isValidBrush = false;

                for (int b = 0; b < leaf.NumLeafBrushes; b++)
                {
                    int      brushID = bspLoader.LeafBrushes[leaf.FirstLeafBrush + b];
                    BspBrush brush   = bspLoader.Brushes[brushID];

                    if (brush.ShaderNum == -1)
                    {
                        continue;
                    }

                    ContentFlags flags = bspLoader.IsVbsp
                        ? (ContentFlags)brush.ShaderNum
                        : bspLoader.Shaders[brush.ShaderNum].ContentFlags;

                    if ((flags & ContentFlags.Solid) == 0)
                    {
                        continue;
                    }

                    var planeEquations = new List <Vector4>();
                    brush.ShaderNum = -1;

                    for (int p = 0; p < brush.NumSides; p++)
                    {
                        int sideId = brush.FirstSide + p;

                        BspBrushSide brushside     = bspLoader.BrushSides[sideId];
                        BspPlane     plane         = bspLoader.Planes[brushside.PlaneNum];
                        Vector4      planeEquation = new Vector4(plane.Normal, scaling * -plane.Distance);
                        planeEquations.Add(planeEquation);
                        isValidBrush = true;
                    }
                    if (isValidBrush)
                    {
                        List <Vector3> vertices     = GeometryUtil.GetVerticesFromPlaneEquations(planeEquations);
                        const bool     isEntity     = false;
                        Vector3        entityTarget = Vector3.Zero;
                        AddConvexVerticesCollider(vertices, isEntity, entityTarget);
                    }
                }
            }

            /*
             * foreach (BspEntity entity in bspLoader.Entities)
             * {
             *  if (entity.ClassName == "trigger_push")
             *  {
             *  }
             * }
             */
        }