#include "doomdata.h" #include "workdata.h" #include "tarray.h" struct FEventInfo { int Vertex; DWORD FrontSeg; }; struct FEvent { FEvent *Parent, *Left, *Right; enum { RED, BLACK } Color; double Distance; FEventInfo Info; }; class FEventTree { public: FEventTree (); ~FEventTree (); FEvent *GetMinimum (); FEvent *GetSuccessor (FEvent *event) const { FEvent *node = Successor(event); return node == &Nil ? NULL : node; } FEvent *GetPredecessor (FEvent *event) const { FEvent *node = Predecessor(event); return node == &Nil ? NULL : node; } FEvent *GetNewNode (); void Insert (FEvent *event); void Delete (FEvent *event); FEvent *FindEvent (double distance) const; void DeleteAll (); void PrintTree () const { PrintTree (Root); } private: FEvent Nil; FEvent *Root; FEvent *Spare; void LeftRotate (FEvent *event); void RightRotate (FEvent *event); void DeleteFixUp (FEvent *event); void DeletionTraverser (FEvent *event); FEvent *Successor (FEvent *event) const; FEvent *Predecessor (FEvent *event) const; void PrintTree (const FEvent *event) const; }; class FNodeBuilder { struct FPrivSeg { int v1, v2; int sidedef; int linedef; int frontsector; int backsector; DWORD next; DWORD nextforvert; DWORD nextforvert2; int loopnum; // loop number for split avoidance (0 means splitting is okay) DWORD partner; // seg on back side DWORD storedseg; // seg # in the GL_SEGS lump angle_t angle; fixed_t offset; int planenum; bool planefront; FPrivSeg *hashnext; }; struct FPrivVert { fixed_t x, y; DWORD segs; // segs that use this vertex as v1 DWORD segs2; // segs that use this vertex as v2 bool operator== (const FPrivVert &other) { return x == other.x && y == other.y; } }; struct FSimpleLine { fixed_t x, y, dx, dy; }; union USegPtr { DWORD SegNum; FPrivSeg *SegPtr; }; struct FSplitSharer { double Distance; DWORD Seg; bool Forward; }; public: struct FPolyStart { int polynum; fixed_t x, y; }; FNodeBuilder (FLevel &level, TArray &polyspots, TArray &anchors, const char *name, bool makeGLnodes); void GetVertices (WideVertex *&verts, int &count); void GetNodes (MapNodeEx *&nodes, int &nodeCount, MapSeg *&segs, int &segCount, MapSubsectorEx *&ssecs, int &subCount); void GetGLNodes (MapNodeEx *&nodes, int &nodeCount, MapSegGLEx *&segs, int &segCount, MapSubsectorEx *&ssecs, int &subCount); // < 0 : in front of line // == 0 : on line // > 0 : behind line static int PointOnSide (int x, int y, int x1, int y1, int dx, int dy); private: TArray Nodes; TArray Subsectors; TArray SubsectorSets; TArray Segs; TArray Vertices; TArray SegList; TArray PlaneChecked; TArray Planes; size_t InitialVertices; // Number of vertices in a map that are connected to linedefs TArray Touched; // Loops a splitter touches on a vertex TArray Colinear; // Loops with edges colinear to a splitter FEventTree Events; // Vertices intersected by the current splitter TArray SplitSharers; // Segs collinear with the current splitter DWORD HackSeg; // Seg to force to back of splitter FLevel &Level; bool GLNodes; // Progress meter stuff int SegsStuffed; const char *MapName; void FindUsedVertices (WideVertex *vertices, int max); int SelectVertexExact (FPrivVert &vertex); void BuildTree (); void MakeSegsFromSides (); FPrivSeg *CheckSegForDuplicate (const FPrivSeg *check); void GroupSegPlanes (); void FindPolyContainers (TArray &spots, TArray &anchors); bool GetPolyExtents (int polynum, fixed_t bbox[4]); int MarkLoop (DWORD firstseg, int loopnum); void AddSegToBBox (fixed_t bbox[4], const FPrivSeg *seg); DWORD CreateNode (DWORD set, fixed_t bbox[4]); DWORD CreateSubsector (DWORD set, fixed_t bbox[4]); void CreateSubsectorsForReal (); bool CheckSubsector (DWORD set, node_t &node, DWORD &splitseg, int setsize); int SelectSplitter (DWORD set, node_t &node, DWORD &splitseg, int step, bool nosplit); void SplitSegs (DWORD set, node_t &node, DWORD splitseg, DWORD &outset0, DWORD &outset1); DWORD SplitSeg (DWORD segnum, int splitvert, int v1InFront); int Heuristic (node_t &node, DWORD set, bool honorNoSplit); int ClassifyLine (node_t &node, const FPrivSeg *seg, int &sidev1, int &sidev2); int CountSegs (DWORD set) const; void FixSplitSharers (); double AddIntersection (const node_t &node, int vertex); void AddMinisegs (const node_t &node, DWORD splitseg, DWORD &fset, DWORD &rset); DWORD CheckLoopStart (fixed_t dx, fixed_t dy, int vertex1, int vertex2); DWORD CheckLoopEnd (fixed_t dx, fixed_t dy, int vertex2); void RemoveSegFromVert1 (DWORD segnum, int vertnum); void RemoveSegFromVert2 (DWORD segnum, int vertnum); DWORD AddMiniseg (int v1, int v2, DWORD partner, DWORD seg1, DWORD splitseg); void SetNodeFromSeg (node_t &node, const FPrivSeg *pseg) const; int RemoveMinisegs (MapNodeEx *nodes, TArray &segs, MapSubsectorEx *subs, int node, short bbox[4]); int StripMinisegs (TArray &segs, int subsector, short bbox[4]); void AddSegToShortBBox (short bbox[4], const FPrivSeg *seg); int CloseSubsector (TArray &segs, int subsector); DWORD PushGLSeg (TArray &segs, const FPrivSeg *seg); void PushConnectingGLSeg (int subsector, TArray &segs, int v1, int v2); int OutputDegenerateSubsector (TArray &segs, int subsector, bool bForward, double lastdot, FPrivSeg *&prev); static int SortSegs (const void *a, const void *b); double InterceptVector (const node_t &splitter, const FPrivSeg &seg); void PrintSet (int l, DWORD set); };