Esempio n. 1
0
        private static RooWall ChooseSplitter(IEnumerable <RooWall> Walls)
        {
            RooWall best_splitter = null;
            int     best_count    = -1;     // Minimum # of walls in bigger side of best wall
            int     best_splits   = 999999; // # of splits for best root so far
            int     max_count;
            int     side0, side1;

            foreach (RooWall splitter in Walls)
            {
                int pos    = 0;
                int neg    = 0;
                int splits = 0;

                foreach (RooWall wall in Walls)
                {
                    side0 = wall.P1.GetSide(splitter.P1, splitter.P2);
                    side1 = wall.P2.GetSide(splitter.P1, splitter.P2);

                    // If both on same side, or one is on line, no split needed
                    if (side0 * side1 >= 0)
                    {
                        // In plane of root?
                        if (side0 == 0 && side1 == 0)
                        {
                            continue;
                        }

                        // On + side of root?
                        if (side0 > 0 || side1 > 0)
                        {
                            pos++;
                            continue;
                        }

                        // On - side of root
                        neg++;
                        continue;
                    }

                    // Split--one on each side
                    pos++;
                    neg++;
                    splits++;
                }

                max_count = Math.Max(pos, neg);

                if (max_count < best_count ||
                    (max_count == best_count && splits < best_splits) ||
                    best_count == -1)
                {
                    best_count    = max_count;
                    best_splitter = splitter;
                    best_splits   = splits;
                }
            }

            return(best_splitter);
        }
Esempio n. 2
0
        public static void Build(RooFile Room)
        {
            if (Room == null)
            {
                return;
            }

            room = Room;

            if (BuildStarted != null)
            {
                BuildStarted(null, new EventArgs());
            }

            ///////////////////////////////////////////////////////////////

            BoundingBox2D box = Room.GetBoundingBox2D(true);

            Polygon poly = new Polygon();

            poly.Add(box.Min);
            poly.Add(box.Min + new V2(box.Max.X - box.Min.X, 0f));
            poly.Add(box.Max);
            poly.Add(box.Max - new V2(box.Max.X - box.Min.X, 0f));

            ///////////////////////////////////////////////////////////////

            // clean up old data from room
            Room.Walls.Clear();
            Room.BSPTree.Clear();
            foreach (RooSector sector in Room.Sectors)
            {
                sector.Walls.Clear();
                sector.Sides.Clear();
            }

            // convert roomeditor walls to roowall
            for (int i = 0; i < Room.WallsEditor.Count; i++)
            {
                RooWall wall = Room.WallsEditor[i].ToRooWall(RooFile.VERSIONHIGHRESGRID, Room);
                Room.Walls.Add(wall);
            }

            ///////////////////////////////////////////////////////////////

            RooBSPItem tree = BuildNode(Room.Walls, poly, 0);

            ///////////////////////////////////////////////////////////////

            FillNode(tree, Room.BSPTree);
            SetNums(Room.BSPTree);
        }
Esempio n. 3
0
        private static void SetNums(List <RooBSPItem> Nodes)
        {
            int idx;
            RooPartitionLine splitter;

            // set wall nums
            for (int i = 0; i < room.Walls.Count; i++)
            {
                RooWall wall = room.Walls[i];
                wall.Num = i + 1;

                if (wall.NextWallInPlane != null)
                {
                    // set 1-based num (0=unset)
                    idx = room.Walls.IndexOf(wall.NextWallInPlane);

                    wall.NextWallNumInPlane = (short)((idx >= 0) ? idx + 1 : 0);
                }
            }

            foreach (RooBSPItem node in Nodes)
            {
                if (node.Type == RooBSPItem.NodeType.Node)
                {
                    splitter = (RooPartitionLine)node;

                    if (splitter.RightChild != null)
                    {
                        idx = Nodes.IndexOf(splitter.RightChild);

                        // set 1-based num (0=unset)
                        splitter.Right = (ushort)((idx >= 0) ? idx + 1 : 0);
                    }

                    if (splitter.LeftChild != null)
                    {
                        idx = Nodes.IndexOf(splitter.LeftChild);

                        // set 1-based num (0=unset)
                        splitter.Left = (ushort)((idx >= 0) ? idx + 1 : 0);
                    }

                    if (splitter.Wall != null)
                    {
                        idx = room.Walls.IndexOf(splitter.Wall);

                        // set 1-based num (0=unset)
                        splitter.WallReference = (ushort)((idx >= 0) ? idx + 1 : 0);
                    }
                }
            }
        }
Esempio n. 4
0
        /// <summary>
        /// Creates a RooWall instance based on this RooWallEditor instance.
        /// </summary>
        /// <param name="RooVersion"></param>
        /// <param name="Room"></param>
        /// <returns></returns>
        public RooWall ToRooWall(uint RooVersion, RooFile Room)
        {
            if (Room == null)
            {
                return(null);
            }

            V2 q1, q2;

            // first try get boundingbox as defined by 'Things'
            BoundingBox2D box = Room.GetBoundingBox2DFromThings();

            // no thingsbox? build based on editorwalls
            if (box == BoundingBox2D.NULL)
            {
                box = Room.GetBoundingBox2D(false);
            }

            // 1) Convert from 1:64 to 1:1024
            // 2) Modify coordinate system (y-axis different)
            q1.X = (P0.X - box.Min.X) * 16f;
            q1.Y = (box.Max.Y - P0.Y) * 16f;
            q2.X = (P1.X - box.Min.X) * 16f;
            q2.Y = (box.Max.Y - P1.Y) * 16f;

            // sidenum in editorwall is  0 to n ( 0=unset)
            // sectnum in editorwall is -1 to n (-1=unset)

            RooWall wall = new RooWall(
                RooVersion,
                0,
                (ushort)this.FileSideDef1, // no +1
                (ushort)this.FileSideDef2, // no +1
                q1,
                q2,
                Side1XOffset,
                Side2XOffset,
                Side1YOffset,
                Side2YOffset,
                (ushort)(Side1Sector + 1),  // +1 mapping
                (ushort)(Side2Sector + 1)); // +1 mapping

            // now resolve the object references from indices
            // and fill in heights
            wall.ResolveIndices(Room);
            wall.CalculateWallSideHeights();

            // done
            return(wall);
        }
        /// <summary>
        /// Splits this wall into two using infinite line given by Q1Q2.
        /// </summary>
        /// <param name="Q1"></param>
        /// <param name="Q2"></param>
        /// <returns>Item1: P1 to I. Item2: I to P2</returns>
        public Tuple<RooWall, RooWall> Split(V2 Q1, V2 Q2)
        {
            V2 intersect;

            // intersect this wall (finite line) with the infinite line given by Q1Q2
            LineInfiniteLineIntersectionType intersecttype =
                MathUtil.IntersectLineInfiniteLine(P1, P2, Q1, Q2, out intersect);

            // must have a real intersection, not only boundarypoint or even coincide
            if (intersecttype != LineInfiniteLineIntersectionType.OneIntersection)
                return null;

            /*****************************************************************/

            // 1) Piece from P1 to intersection
            RooWall wall1 = new RooWall(
                RooVersion,
                NextWallNumInPlane,
                RightSideNum,
                LeftSideNum,
                P1,
                intersect,
                RightXOffset,  // readjust below
                LeftXOffset,   // readjust below
                RightYOffset,  // readjust below
                LeftYOffset,   // readjust below
                RightSectorNum,
                LeftSectorNum
                );

            // also keep references of old wall
            wall1.RightSector = RightSector;
            wall1.LeftSector = LeftSector;
            wall1.RightSide = RightSide;
            wall1.LeftSide = LeftSide;
            wall1.BowtieFlags = BowtieFlags;
            wall1.CalculateWallSideHeights();

            /*****************************************************************/

            // 2) Piece from intersection to P2
            RooWall wall2 = new RooWall(
                RooVersion,
                NextWallNumInPlane,
                RightSideNum,
                LeftSideNum,
                intersect,
                P2,
                RightXOffset,  // readjust below
                LeftXOffset,   // readjust below
                RightYOffset,  // readjust below
                LeftYOffset,   // readjust below
                RightSectorNum,
                LeftSectorNum
                );

            // also keep references of old wall
            wall2.RightSector = RightSector;
            wall2.LeftSector = LeftSector;
            wall2.RightSide = RightSide;
            wall2.LeftSide = LeftSide;
            wall2.BowtieFlags = BowtieFlags;
            wall2.CalculateWallSideHeights();

            /*****************************************************************/

            // 3) Readjust texture offsets to accoutn for split

            // RightSide
            if (wall1.RightSide != null && wall1.RightSide.Flags.IsBackwards)
                wall1.RightXOffset += (short)wall2.ClientLength;
            else wall2.RightXOffset += (short)wall1.ClientLength;

            // LeftSide (Do this backwards, because client exchanges vertices of negative walls)
            if (wall1.LeftSide != null && wall1.LeftSide.Flags.IsBackwards)
                wall2.LeftXOffset += (short)wall1.ClientLength;
            else wall1.LeftXOffset += (short)wall2.ClientLength;

            /*****************************************************************/

            return new Tuple<RooWall, RooWall>(wall1, wall2);
        }
Esempio n. 6
0
        /// <summary>
        /// Creates object references from the Sector/Side Num references.
        /// </summary>
        /// <param name="RooFile"></param>
        public void ResolveIndices(RooFile RooFile)
        {
            // num properties are not zero-based, but the arrays are

            // get reference to right SectorDef
            if (RightSectorNum > 0 && 
                RooFile.Sectors.Count > RightSectorNum - 1)
            {
                RightSector = RooFile.Sectors[RightSectorNum - 1];

                // save as adjacent wall
                if (!RightSector.Walls.Contains(this))
                    RightSector.Walls.Add(this);
            }

            // get reference to left SectorDef
            if (LeftSectorNum > 0 &&
                RooFile.Sectors.Count > LeftSectorNum - 1)
            {
                LeftSector = RooFile.Sectors[LeftSectorNum - 1];

                // save as adjacent wall
                if (!LeftSector.Walls.Contains(this))
                    LeftSector.Walls.Add(this);
            }

            // get reference to right SideDef
            if (RightSideNum > 0 &&
                RooFile.SideDefs.Count > RightSideNum - 1)
            {
                RightSide = RooFile.SideDefs[RightSideNum - 1];

                // save as adjacent side
                if (RightSector != null && !RightSector.Sides.Contains(RightSide))
                    RightSector.Sides.Add(RightSide);

                // save as adjacent side
                if (LeftSector != null && !LeftSector.Sides.Contains(RightSide))
                    LeftSector.Sides.Add(RightSide);
            }

            // get reference to left SideDef
            if (LeftSideNum > 0 &&
                RooFile.SideDefs.Count > LeftSideNum - 1)
            {
                LeftSide = RooFile.SideDefs[LeftSideNum - 1];

                // save as adjacent side
                if (RightSector != null && !RightSector.Sides.Contains(LeftSide))
                    RightSector.Sides.Add(LeftSide);

                // save as adjacent side
                if (LeftSector != null && !LeftSector.Sides.Contains(LeftSide))
                    LeftSector.Sides.Add(LeftSide);
            }

            // get reference to next wall in same plane
            if (NextWallNumInPlane > 0 &&
                RooFile.Walls.Count > NextWallNumInPlane - 1)
            {
                NextWallInPlane = RooFile.Walls[NextWallNumInPlane - 1];
            }
        }
Esempio n. 7
0
        private static RooBSPItem BuildNode(List <RooWall> Walls, Polygon Polygon, int Sector)
        {
            if (Polygon.Count == 0 || (Walls.Count == 0 && Sector == 0))
            {
                return(null);
            }

            Polygon.RemoveZeroEdges();

            if (!Polygon.IsConvexPolygon())
            {
                if (FoundNonConvexPolygon != null)
                {
                    FoundNonConvexPolygon(null, new PolygonEventArgs(Polygon));
                }

                //return null; // WTF ?
            }

            // No walls left ==> leaf
            if (Walls.Count == 0)
            {
                RooSubSector leaf = new RooSubSector(RooFile.VERSIONHIGHRESGRID, (ushort)Sector, Polygon);

                // fills in sector reference
                leaf.ResolveIndices(room);

                return(leaf);
            }

            // get best splitter of remaining walls
            RooWall splitter = ChooseSplitter(Walls);

            if (splitter == null)
            {
                return(null); // WTF ?
            }
            // split up walls into right/left
            Tuple <List <RooWall>, List <RooWall> > splitWalls =
                SplitWalls(Walls, splitter);

            // split up polygon into right/left
            Tuple <Polygon, Polygon> splitPolygons =
                Polygon.SplitConvexPolygon(splitter.P1, splitter.P2);

            Real a, b, c;

            GetLineEquation2DCoefficients(splitter.P1, splitter.P2,
                                          out a, out b, out c);

            // create new splitter node
            RooPartitionLine node = new RooPartitionLine(RooFile.VERSIONHIGHRESGRID,
                                                         Polygon.GetBoundingBox(), a, b, c, 0, 0, (ushort)splitter.Num);

            // fills in wall reference
            node.Wall = splitter;

            // recursively descend to children
            node.LeftChild  = BuildNode(splitWalls.Item1, splitPolygons.Item1, splitter.LeftSectorNum);
            node.RightChild = BuildNode(splitWalls.Item2, splitPolygons.Item2, splitter.RightSectorNum);

            return(node);
        }
Esempio n. 8
0
        private static Tuple <List <RooWall>, List <RooWall> > SplitWalls(List <RooWall> Walls, RooWall Splitter)
        {
            int            side0, side1;
            List <RooWall> wallsRight = new List <RooWall>();
            List <RooWall> wallsLeft  = new List <RooWall>();

            // backwards due to removing items
            for (int i = Walls.Count - 1; i >= 0; i--)
            {
                RooWall wall = Walls[i];

                if (wall == Splitter)
                {
                    continue;
                }

                side0 = wall.P1.GetSide(Splitter.P1, Splitter.P2);
                side1 = wall.P2.GetSide(Splitter.P1, Splitter.P2);

                // coincide =
                // both endpoints on wall
                if (side0 == 0 && side1 == 0)
                {
                    // attach at end of linked list if not already included
                    bool    add  = true;
                    RooWall next = Splitter;
                    while (next.NextWallInPlane != null)
                    {
                        // already in there
                        if (next.NextWallInPlane == wall)
                        {
                            add = false;
                            break;
                        }

                        next = next.NextWallInPlane;
                    }

                    if (add)
                    {
                        next.NextWallInPlane = wall;
                    }

                    continue;
                }

                // on right side =
                // both endpoints right side, or one right, one on line
                if (side0 <= 0 && side1 <= 0)
                {
                    wallsRight.Add(wall);
                    continue;
                }

                // on left side
                // both endpoints left side, or one left, one on line
                if (side0 >= 0 && side1 >= 0)
                {
                    wallsLeft.Add(wall);
                    continue;
                }

                // intersection - split the wall
                Tuple <RooWall, RooWall> splitWall = wall.Split(Splitter.P1, Splitter.P2);

                // remove old wall and add new chunks
                // second first so first will be first
                int idx = room.Walls.IndexOf(wall);
                room.Walls.RemoveAt(idx);
                room.Walls.Insert(idx, splitWall.Item2);
                room.Walls.Insert(idx, splitWall.Item1);

                if (splitWall != null)
                {
                    // if p1 was on right side and p2 on left side
                    // add the segment p1 to intersect to right walls
                    // add the segment intersect to p2 to left walls
                    if (side0 < 0 && side1 > 0)
                    {
                        wallsRight.Add(splitWall.Item1);
                        wallsLeft.Add(splitWall.Item2);
                    }
                    // other way round
                    else
                    {
                        wallsLeft.Add(splitWall.Item1);
                        wallsRight.Add(splitWall.Item2);
                    }
                }
                else
                {
                    return(null); // WTF?
                }
            }

            return(new Tuple <List <RooWall>, List <RooWall> >(wallsRight, wallsLeft));
        }
Esempio n. 9
0
        protected void DrawWall(Graphics G, RooWall Wall, Pen Pen, bool Infinite, Pen PenInfinite)
        {
            V2 p1p2;

            // transform points to match world of pixeldrawing
            float transx1 = (float)(Wall.P1.X - boxMin.X) * ZoomInv;
            float transy1 = (float)(Wall.P1.Y - boxMin.Y) * ZoomInv;
            float transx2 = (float)(Wall.P2.X - boxMin.X) * ZoomInv;
            float transy2 = (float)(Wall.P2.Y - boxMin.Y) * ZoomInv;

            // draw extensions of line
            if (Infinite)
            {
                V2 p1 = new V2(transx1, transy1);
                V2 p2 = new V2(transx2, transy2);
                p1p2 = p2 - p1;

                p2 += 1000f * p1p2;
                p1 -= 1000f * p1p2;

                G.DrawLine(PenInfinite, (float)p1.X, (float)p1.Y, (float)p2.X, (float)p2.Y);
            }

            // check if this is an issue line (almost horizontal or vertical, but not fully)
            p1p2 = Wall.GetP1P2();
            if (chkVertHortLines.Checked && p1p2.X != 0.0f && p1p2.Y != 0.0f)
            {
                Real m = (Real)(p1p2.Y / p1p2.X);

                if ((m > -0.125f && m < 0.125f) ||
                    (m > 8.0f || m < -8.0f))
                        Pen = penRed2;
            }
            
            // draw line
            G.DrawLine(Pen, transx1, transy1, transx2, transy2);           
        }
Esempio n. 10
0
        private static Tuple<List<RooWall>, List<RooWall>> SplitWalls(List<RooWall> Walls, RooWall Splitter)
        {
            int side0, side1;
            List<RooWall> wallsRight = new List<RooWall>();
            List<RooWall> wallsLeft  = new List<RooWall>();
            
            // backwards due to removing items
            for(int i = Walls.Count - 1 ; i >= 0; i--)
            {
                RooWall wall = Walls[i];

                if (wall == Splitter)
                    continue;

                side0 = wall.P1.GetSide(Splitter.P1, Splitter.P2);
                side1 = wall.P2.GetSide(Splitter.P1, Splitter.P2);

                // coincide =
                // both endpoints on wall
                if (side0 == 0 && side1 == 0)
                {
                    // attach at end of linked list if not already included
                    bool add = true;
                    RooWall next = Splitter;
                    while (next.NextWallInPlane != null) 
                    {
                        // already in there
                        if (next.NextWallInPlane == wall)
                        {
                            add = false;
                            break;
                        }

                        next = next.NextWallInPlane;
                    }

                    if (add)
                        next.NextWallInPlane = wall;
                    
                    continue;
                }
                
                // on right side =
                // both endpoints right side, or one right, one on line
                if (side0 <= 0 && side1 <= 0)
                {
                    wallsRight.Add(wall);
                    continue;
                }

                // on left side
                // both endpoints left side, or one left, one on line
                if (side0 >= 0 && side1 >= 0)
                {
                    wallsLeft.Add(wall);
                    continue;
                }

                // intersection - split the wall
                Tuple<RooWall, RooWall> splitWall = wall.Split(Splitter.P1, Splitter.P2);

                // remove old wall and add new chunks
                // second first so first will be first
                int idx = room.Walls.IndexOf(wall);
                room.Walls.RemoveAt(idx);
                room.Walls.Insert(idx, splitWall.Item2);
                room.Walls.Insert(idx, splitWall.Item1);

                if (splitWall != null)
                {
                    // if p1 was on right side and p2 on left side
                    // add the segment p1 to intersect to right walls
                    // add the segment intersect to p2 to left walls
                    if (side0 < 0 && side1 > 0)
                    {
                        wallsRight.Add(splitWall.Item1);
                        wallsLeft.Add(splitWall.Item2);
                    }
                    // other way round
                    else
                    {
                        wallsLeft.Add(splitWall.Item1);
                        wallsRight.Add(splitWall.Item2);
                    }
                }
                else
                    return null; // WTF?
            }

            return new Tuple<List<RooWall>, List<RooWall>>(wallsRight, wallsLeft);
        }
        public int ReadFrom(byte[] Buffer, int StartIndex = 0)
        {
            int cursor = StartIndex;

            uint signature = BitConverter.ToUInt32(Buffer, cursor);
            cursor += TypeSizes.INT;

            if (signature == SIGNATURE)
            {
                RooVersion = BitConverter.ToUInt32(Buffer, cursor);
                cursor += TypeSizes.INT;

                // supported version ?
                if (RooVersion >= RooFile.MINVERSION)
                {
                    Challenge = BitConverter.ToUInt32(Buffer, cursor);
                    cursor += TypeSizes.INT;

                    OffsetClient = BitConverter.ToUInt32(Buffer, cursor);
                    cursor += TypeSizes.INT;

                    OffsetServer = BitConverter.ToInt32(Buffer, cursor);
                    cursor += TypeSizes.INT;
                }
                else
                    throw new Exception("RooVersion too old, got: " + RooVersion + " Expected greater " + RooFile.MINVERSION);
            }
            else
                throw new Exception("Wrong file signature: " + signature + " (expected " + SIGNATURE + ").");

            //
            // Client part (was encrypted once)
            //

            // Check if file is encrypted
            if (BitConverter.ToUInt32(Buffer, cursor) == ENCRYPTIONFLAG)
            {
            #if WINCLR && X86
                EncryptionEnabled = true;
                cursor += TypeSizes.INT;

                // get additional values for decryption
                EncryptedStreamLength = BitConverter.ToInt32(Buffer, cursor);
                cursor += TypeSizes.INT;

                ExpectedResponse = BitConverter.ToUInt32(Buffer, cursor);
                cursor += TypeSizes.INT;

                Crush32.Decrypt(Buffer, cursor, EncryptedStreamLength, Challenge, ExpectedResponse, GetPassword());
            #else
                throw new Exception(ERRORCRUSHPLATFORM);
            #endif
            }
            else
                EncryptionEnabled = false;

            // Get the basic infos, like room dimension and section offsets
            RoomSizeX = BitConverter.ToUInt32(Buffer, cursor);
            cursor += TypeSizes.INT;

            RoomSizeY = BitConverter.ToUInt32(Buffer, cursor);
            cursor += TypeSizes.INT;

            OffsetBSPTree = BitConverter.ToInt32(Buffer, cursor);
            cursor += TypeSizes.INT;

            OffsetWalls = BitConverter.ToInt32(Buffer, cursor);
            cursor += TypeSizes.INT;

            OffsetWallsEditor = BitConverter.ToInt32(Buffer, cursor);
            cursor += TypeSizes.INT;

            OffsetSideDefs = BitConverter.ToInt32(Buffer, cursor);
            cursor += TypeSizes.INT;

            OffsetSectors = BitConverter.ToInt32(Buffer, cursor);
            cursor += TypeSizes.INT;

            OffsetThings = BitConverter.ToInt32(Buffer, cursor);
            cursor += TypeSizes.INT;

            // used to save section item counts
            ushort len;

            // Section 1: BSP-Tree
            cursor = OffsetBSPTree + (Convert.ToByte(EncryptionEnabled) * 12);
            len = BitConverter.ToUInt16(Buffer, cursor);
            cursor += TypeSizes.SHORT;

            BSPTree = new List<RooBSPItem>(len);
            for (int i = 0; i < len; i++)
            {
                RooBSPItem bspItem = RooBSPItem.ExtractBSPItem(RooVersion, Buffer, cursor);
                cursor += bspItem.ByteLength;

                BSPTree.Add(bspItem);
            }

            // Section 2: Walls
            cursor = OffsetWalls + (Convert.ToByte(EncryptionEnabled) * 12);
            len = BitConverter.ToUInt16(Buffer, cursor);
            cursor += TypeSizes.SHORT;

            Walls = new List<RooWall>(len);
            for (int i = 0; i < len; i++)
            {
                RooWall lineDef = new RooWall(RooVersion, Buffer, cursor);
                cursor += lineDef.ByteLength;

                lineDef.Num = i + 1;
                Walls.Add(lineDef);
            }

            // Section 3: WallsEditor
            cursor = OffsetWallsEditor + (Convert.ToByte(EncryptionEnabled) * 12);
            len = BitConverter.ToUInt16(Buffer, cursor);
            cursor += TypeSizes.SHORT;

            WallsEditor = new List<RooWallEditor>(len);
            for (int i = 0; i < len; i++)
            {
                RooWallEditor wallEditor = new RooWallEditor(Buffer, cursor);
                cursor += wallEditor.ByteLength;

                wallEditor.Num = i + 1;
                WallsEditor.Add(wallEditor);
            }

            // Section 4: SideDefs
            cursor = OffsetSideDefs + (Convert.ToByte(EncryptionEnabled) * 12);
            len = BitConverter.ToUInt16(Buffer, cursor);
            cursor += TypeSizes.SHORT;

            SideDefs = new List<RooSideDef>(len);
            for (int i = 0; i < len; i++)
            {
                RooSideDef sideDef = new RooSideDef(Buffer, cursor);
                cursor += sideDef.ByteLength;

                sideDef.Num = i + 1;
                sideDef.TextureChanged += OnSideTextureChanged;
                SideDefs.Add(sideDef);
            }

            // Section 5: Sectors
            cursor = OffsetSectors + (Convert.ToByte(EncryptionEnabled) * 12);
            len = BitConverter.ToUInt16(Buffer, cursor);
            cursor += TypeSizes.SHORT;

            bool hasSpeed = (RooVersion >= VERSIONSPEED);
            Sectors = new List<RooSector>(len);
            for (int i = 0; i < len; i++)
            {
                RooSector sectorDef = new RooSector(RooVersion, Buffer, cursor, hasSpeed);
                cursor += sectorDef.ByteLength;

                sectorDef.Num = i + 1;
                sectorDef.TextureChanged += OnSectorTextureChanged;
                sectorDef.Moved += OnSectorMoved;
                Sectors.Add(sectorDef);
            }

            // Section 6: Things
            cursor = OffsetThings + (Convert.ToByte(EncryptionEnabled) * 12);
            len = BitConverter.ToUInt16(Buffer, cursor);
            cursor += TypeSizes.SHORT;

            Things = new List<RooThing>(len);
            if (len > 2)
            {
                for (int i = 0; i < len; i++)
                {
                    RooThingExtended rooThing = new RooThingExtended(Buffer, cursor);
                    cursor += rooThing.ByteLength;

                    Things.Add(rooThing);
                }
            }
            else
            {
                for (int i = 0; i < len; i++)
                {
                    RooThing rooThing = new RooThing(Buffer, cursor);
                    cursor += rooThing.ByteLength;

                    Things.Add(rooThing);
                }
            }

            // some older maps don't have the roomid
            // so if we've already reached the serveroffset, set it to 0
            if (cursor == OffsetServer)
            {
                RoomID = 0;
            }
            else
            {
                // get roomid
                RoomID = BitConverter.ToInt32(Buffer, cursor);
                cursor += TypeSizes.INT;
            }

            //
            // Server part
            //

            // load grids
            Grids = new RooGrids(RooVersion, Buffer, cursor);
            cursor += Grids.ByteLength;

            return cursor - StartIndex;
        }
        public unsafe void ReadFrom(ref byte* Buffer)
        {
            // save the startptr, we need it later
            byte* readStartPtr = Buffer;

            uint signature = *((uint*)Buffer);
            Buffer += TypeSizes.INT;

            if (signature == SIGNATURE)
            {
                RooVersion = *((uint*)Buffer);
                Buffer += TypeSizes.INT;

                // supported version ?
                if (RooVersion >= RooFile.MINVERSION)
                {
                    Challenge = *((uint*)Buffer);
                    Buffer += TypeSizes.INT;

                    OffsetClient = *((uint*)Buffer);
                    Buffer += TypeSizes.INT;

                    OffsetServer = *((int*)Buffer);
                    Buffer += TypeSizes.INT;
                }
                else
                    throw new Exception("RooVersion too old, got: " + RooVersion + " Expected greater " + RooFile.MINVERSION);
            }
            else
                throw new Exception("Wrong file signature: " + signature + " (expected " + SIGNATURE + ").");

            //
            // Client part (was encrypted once)
            //

            // Check if file is encrypted
            if (*((uint*)Buffer) == ENCRYPTIONFLAG)
            {
            #if WINCLR && X86
                EncryptionEnabled = true;
                Buffer += TypeSizes.INT;

                // get additional values for decryption
                EncryptedStreamLength = *((int*)Buffer);
                Buffer += TypeSizes.INT;

                ExpectedResponse = *((uint*)Buffer);
                Buffer += TypeSizes.INT;

                Crush32.Decrypt(Buffer, EncryptedStreamLength, Challenge, ExpectedResponse, GetPassword());
            #else
                throw new Exception(ERRORCRUSHPLATFORM);
            #endif
            }
            else
                EncryptionEnabled = false;

            // Get the basic infos, like room dimension and section offsets
            RoomSizeX = *((uint*)Buffer);
            Buffer += TypeSizes.INT;

            RoomSizeY = *((uint*)Buffer);
            Buffer += TypeSizes.INT;

            OffsetBSPTree = *((int*)Buffer);
            Buffer += TypeSizes.INT;

            OffsetWalls = *((int*)Buffer);
            Buffer += TypeSizes.INT;

            OffsetWallsEditor = *((int*)Buffer);
            Buffer += TypeSizes.INT;

            OffsetSideDefs = *((int*)Buffer);
            Buffer += TypeSizes.INT;

            OffsetSectors = *((int*)Buffer);
            Buffer += TypeSizes.INT;

            OffsetThings = *((int*)Buffer);
            Buffer += TypeSizes.INT;

            // used to save section item counts
            ushort len;

            // Section 1: BSP-Tree
            len = *((ushort*)Buffer);
            Buffer += TypeSizes.SHORT;

            BSPTree = new List<RooBSPItem>(len);
            for (int i = 0; i < len; i++)
            {
                RooBSPItem bspItem = RooBSPItem.ExtractBSPItem(RooVersion, ref Buffer);

                BSPTree.Add(bspItem);
            }

            // Section 2: Walls
            len = *((ushort*)Buffer);
            Buffer += TypeSizes.SHORT;

            Walls = new List<RooWall>(len);
            for (int i = 0; i < len; i++)
            {
                RooWall lineDef = new RooWall(RooVersion, ref Buffer);

                lineDef.Num = i + 1;
                Walls.Add(lineDef);
            }

            // Section 3: WallsEditor
            len = *((ushort*)Buffer);
            Buffer += TypeSizes.SHORT;

            WallsEditor = new List<RooWallEditor>(len);
            for (int i = 0; i < len; i++)
            {
                RooWallEditor wallEditor = new RooWallEditor(ref Buffer);

                wallEditor.Num = i + 1;
                WallsEditor.Add(wallEditor);
            }

            // Section 4: SideDefs
            len = *((ushort*)Buffer);
            Buffer += TypeSizes.SHORT;

            SideDefs = new List<RooSideDef>(len);
            for (int i = 0; i < len; i++)
            {
                RooSideDef sideDef = new RooSideDef(ref Buffer);

                sideDef.Num = i + 1;
                sideDef.TextureChanged += OnSideTextureChanged;
                SideDefs.Add(sideDef);
            }

            // Section 5: Sectors
            len = *((ushort*)Buffer);
            Buffer += TypeSizes.SHORT;

            bool hasSpeed = (RooVersion >= VERSIONSPEED);
            Sectors = new List<RooSector>(len);
            for (int i = 0; i < len; i++)
            {
                RooSector sectorDef = new RooSector(RooVersion, ref Buffer, hasSpeed);
                sectorDef.TextureChanged += OnSectorTextureChanged;
                sectorDef.Moved += OnSectorMoved;
                sectorDef.Num = i + 1;
                Sectors.Add(sectorDef);
            }

            // Section 6: Things
            // There is old and new variant of "thing"
            len = *((ushort*)Buffer);
            Buffer += TypeSizes.SHORT;

            Things = new List<RooThing>(len);
            if (len > 2)
            {
                for (int i = 0; i < len; i++)
                    Things.Add(new RooThingExtended(ref Buffer));
            }
            else
            {
                for (int i = 0; i < len; i++)
                    Things.Add(new RooThing(ref Buffer));
            }

            // some older maps don't have the roomid
            // so if we've already reached the serveroffset, set it to 0
            if (Buffer - readStartPtr == OffsetServer)
            {
                RoomID = 0;
            }
            else
            {
                // roomid
                RoomID = *((int*)Buffer);
                Buffer += TypeSizes.INT;
            }

            //
            // Server part
            //

            Grids = new RooGrids(RooVersion, ref Buffer);
        }
Esempio n. 13
0
        /// <summary>
        /// Collisions with wall segments for user movements using the BSP tree.
        /// Therefore with logarithmic rather than linear costs.
        /// </summary>
        /// <param name="Node"></param>
        /// <param name="Start"></param>
        /// <param name="End"></param>
        /// <param name="PlayerHeight"></param>
        /// <param name="IgnoreWall"></param>
        /// <returns></returns>
        protected RooWall VerifyMoveByTree(RooBSPItem Node, V3 Start, V2 End, Real PlayerHeight, RooWall IgnoreWall = null)
        {
            if (Node == null || Node.Type != RooBSPItem.NodeType.Node)
                return null;

            /*************************************************************/

            RooPartitionLine line = (RooPartitionLine)Node;
            RooWall wall = line.Wall;
            V2 start2D = new V2(Start.X, Start.Z);

            /*************************************************************/
            
            // check node boundingbox
            if (!line.BoundingBox.IsInside(End, GeometryConstants.WALLMINDISTANCE) && 
                !line.BoundingBox.IsInside(start2D, GeometryConstants.WALLMINDISTANCE))
                return null;
       
            /*************************************************************/

            // test walls of splitter
            while (wall != null)
            {
                if (wall != IgnoreWall && wall.IsBlockingMove(Start, End, PlayerHeight))
                    return wall;

                // loop over next wall in same plane
                wall = wall.NextWallInPlane;
            }

            /*************************************************************/

            RooWall wl = VerifyMoveByTree(line.LeftChild, Start, End, PlayerHeight, IgnoreWall);

            if (wl != null)
                return wl;

            else
                return VerifyMoveByTree(line.RightChild, Start, End, PlayerHeight, IgnoreWall);
        }
Esempio n. 14
0
        /// <summary>
        /// Creates a RooWall instance based on this RooWallEditor instance.
        /// </summary>
        /// <param name="RooVersion"></param>
        /// <param name="Room"></param>
        /// <returns></returns>
        public RooWall ToRooWall(uint RooVersion, RooFile Room)
        {
            if (Room == null)
                return null;

            V2 q1, q2;

            // first try get boundingbox as defined by 'Things'
            BoundingBox2D box = Room.GetBoundingBox2DFromThings();
            
            // no thingsbox? build based on editorwalls
            if (box == BoundingBox2D.NULL)
                box = Room.GetBoundingBox2D(false);
   
            // 1) Convert from 1:64 to 1:1024
            // 2) Modify coordinate system (y-axis different)
            q1.X = (P0.X - box.Min.X) * 16f;
            q1.Y = (box.Max.Y - P0.Y) * 16f;
            q2.X = (P1.X - box.Min.X) * 16f;
            q2.Y = (box.Max.Y - P1.Y) * 16f;

            // sidenum in editorwall is  0 to n ( 0=unset)
            // sectnum in editorwall is -1 to n (-1=unset)

            RooWall wall = new RooWall(
                RooVersion,
                0,
                (ushort)this.FileSideDef1, // no +1
                (ushort)this.FileSideDef2, // no +1
                q1, 
                q2,
                Side1XOffset, 
                Side2XOffset, 
                Side1YOffset, 
                Side2YOffset,
                (ushort)(Side1Sector + 1),  // +1 mapping 
                (ushort)(Side2Sector + 1)); // +1 mapping

            // now resolve the object references from indices
            // and fill in heights
            wall.ResolveIndices(Room);
            wall.CalculateWallSideHeights();

            // done
            return wall;
        }