| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511 |
- /*
- ** Command & Conquer Renegade(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /***********************************************************************************************
- *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
- ***********************************************************************************************
- * *
- * Project Name : LevelEdit *
- * *
- * $Archive:: /Commando/Code/wwphys/floodfillbox.h $*
- * *
- * Author:: Patrick Smith *
- * *
- * $Modtime:: 5/03/01 10:27a $*
- * *
- * $Revision:: 3 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #if defined(_MSC_VER)
- #pragma once
- #endif
- #ifndef __FLOODFILLBOX_H
- #define __FLOODFILLBOX_H
- #include "vector3.h"
- #include "matrix3d.h"
- #include "vector.h"
- #include "refcount.h"
- #include "bittype.h"
- //////////////////////////////////////////////////////////////////////////
- // Forward delcarations
- //////////////////////////////////////////////////////////////////////////
- class FloodfillBoxClass;
- class PathfindSectorClass;
- class PathfindPortalClass;
- //////////////////////////////////////////////////////////////////////////
- // Data types
- //////////////////////////////////////////////////////////////////////////
- typedef DynamicVectorClass<FloodfillBoxClass *> BODY_BOX_LIST;
- typedef enum
- {
- DIR_FORWARD = 0,
- DIR_LEFT,
- DIR_BACKWARD,
- DIR_RIGHT,
- DIR_MAX,
- DIR_UP = DIR_FORWARD,
- DIR_DOWN = DIR_BACKWARD,
- } PATHFIND_DIR;
- typedef enum
- {
- MASK_NONE = 0,
- MASK_FORWARD = 1,
- MASK_LEFT = 2,
- MASK_BACKWARD = 4,
- MASK_RIGHT = 8,
- MASK_MAX,
-
- MASK_UP = MASK_FORWARD,
- MASK_DOWN = MASK_BACKWARD,
- } DIRECTION_MASK;
- inline PATHFIND_DIR
- Mask_to_Dir (DIRECTION_MASK mask)
- {
- for (int dir = 0; dir < DIR_MAX; dir ++) {
- if ((1 << dir) == mask) {
- return PATHFIND_DIR(dir);
- }
- }
- return DIR_MAX;
- }
- inline PATHFIND_DIR
- Inverse_Pathfind_Dir (PATHFIND_DIR dir)
- {
- if (dir < 2) return PATHFIND_DIR(dir + 2);
- return PATHFIND_DIR(dir - 2);
- }
- inline PATHFIND_DIR
- Clockwise_Pathfind_Dir (PATHFIND_DIR dir)
- {
- return PATHFIND_DIR((dir + 3) % DIR_MAX);
- }
- //////////////////////////////////////////////////////////////////////////
- //
- // FloodfillBoxClass
- //
- //////////////////////////////////////////////////////////////////////////
- class FloodfillBoxClass : public RefCountClass
- {
- public:
- //////////////////////////////////////////////////////////////////////
- // Public constructors/destructors
- //////////////////////////////////////////////////////////////////////
- FloodfillBoxClass (void)
- : m_Sector (NULL),
- m_Flags (NeedsProcessing),
- m_DirectionInfo (0),
- m_CompressedSkipCount (0),
- m_MinZPos (0),
- m_MaxZPos (0),
- m_GridLink (NULL),
- m_Prev (NULL),
- m_Next (NULL) { ::memset (m_Neighbors, 0, sizeof (m_Neighbors)); }
- virtual ~FloodfillBoxClass (void) { Remove (); }
- //////////////////////////////////////////////////////////////////////
- // Access to the Position/Orientation state of the object
- //////////////////////////////////////////////////////////////////////
- Vector3 Get_Position (void) const { return m_Position; }
- void Set_Position (const Vector3 &pos) { m_Position = pos; }
- float Get_Min_Z_Pos (void) const { return m_MinZPos; }
- float Get_Max_Z_Pos (void) const { return m_MaxZPos; }
- void Set_Min_Z_Pos (float pos) { m_MinZPos = pos; }
- void Set_Max_Z_Pos (float pos) { m_MaxZPos = pos; }
- Vector3 Get_Center (void) const;
- Vector3 Get_Extent (void) const;
- //////////////////////////////////////////////////////////////////////
- // Timestep methods
- //////////////////////////////////////////////////////////////////////
- void Timestep (float dt) {}
- //////////////////////////////////////////////////////////////////////
- // Adjacent sector methods
- //////////////////////////////////////////////////////////////////////
- FloodfillBoxClass * Peek_Neighbor (PATHFIND_DIR dir, bool only_traversible = true);
- void Set_Neighbor (PATHFIND_DIR dir, FloodfillBoxClass *obj, bool traversible);
- FloodfillBoxClass * Find_Relative (int x, int y);
- bool Is_Two_Way_Traversible (PATHFIND_DIR dir);
- void Set_Taken (bool onoff = true) { Set_Flag (IsTaken, onoff); }
- bool Is_Taken (void) { return bool((m_Flags & IsTaken) == IsTaken); }
- uint8 Get_Compress_Skipped_Count (void) { return m_CompressedSkipCount; }
- void Inc_Compress_Skipped_Count (void) { m_CompressedSkipCount ++; }
- //////////////////////////////////////////////////////////////////////
- // Delayed processing methods
- //////////////////////////////////////////////////////////////////////
- bool Needs_Processing (void) const { return bool((m_Flags & NeedsProcessing) == NeedsProcessing); }
- void Needs_Processing (bool needs_it) { Set_Flag (NeedsProcessing, needs_it); }
- //////////////////////////////////////////////////////////////////////
- // Linked list methods
- //////////////////////////////////////////////////////////////////////
- static FloodfillBoxClass * Get_First (void) { return m_First; }
- static FloodfillBoxClass * Get_Last (void) { return m_Last; }
- FloodfillBoxClass * Get_Next (void) { return m_Next; }
- FloodfillBoxClass * Get_Prev (void) { return m_Prev; }
- void Set_Next (FloodfillBoxClass *next) { m_Next = next; }
- void Set_Prev (FloodfillBoxClass *prev) { m_Prev = prev; }
- static void Add (FloodfillBoxClass *new_obj);
- void Remove (void);
- void Unlink (void);
- bool Is_Edge (void);
- bool Are_Neighbors_Processed (void);
- //////////////////////////////////////////////////////////////////////
- // Portal generation methods
- //////////////////////////////////////////////////////////////////////
- PathfindSectorClass * Peek_Sector (void) { return m_Sector; }
- void Set_Sector (PathfindSectorClass *sector) { m_Sector = sector; }
- bool Is_New_Portal (PATHFIND_DIR dir, PathfindSectorClass *dest_sector = NULL);
- PathfindPortalClass * Make_Portal (PATHFIND_DIR dir, const Vector3 &box_size, float z_pos, float min_acceptable_size);
- void Reset_Portal_Info (void) { (m_DirectionInfo &= ~PortalMask); }
- void Part_Of_Portal (PATHFIND_DIR dir, bool onoff);
- bool Part_Of_Portal (PATHFIND_DIR dir);
- //////////////////////////////////////////////////////////////////////
- // Grid link methods
- //////////////////////////////////////////////////////////////////////
- FloodfillBoxClass * Get_Grid_Link (void) { return m_GridLink; }
- void Set_Grid_Link (FloodfillBoxClass *link) { m_GridLink = link; }
- protected:
- //////////////////////////////////////////////////////////////////////
- // Protected methods
- //////////////////////////////////////////////////////////////////////
- void Set_Flag (uint8 flag, bool value);
- void Set_Traversible (PATHFIND_DIR dir, bool onoff);
- bool Get_Traversible (PATHFIND_DIR dir);
- private:
- //////////////////////////////////////////////////////////////////////
- // Private methods
- //////////////////////////////////////////////////////////////////////
-
- typedef enum
- {
- IsTaken = 0x01,
- NeedsProcessing = 0x02,
- } Flags;
- typedef enum
- {
- IsTraversibleUp = 0x01,
- IsTraversibleLeft = 0x02,
- IsTraversibleDown = 0x04,
- IsTraversibleRight = 0x08,
- TraversibleMask = 0x0F,
- IsPortalUp = 0x10,
- IsPortalLeft = 0x20,
- IsPortalDown = 0x40,
- IsPortalRight = 0x80,
- PortalMask = 0xF0,
- } Directions;
- //////////////////////////////////////////////////////////////////////
- // Private member data
- //////////////////////////////////////////////////////////////////////
- FloodfillBoxClass * m_Neighbors[4];
- uint8 m_Flags;
- uint8 m_DirectionInfo;
- uint8 m_CompressedSkipCount;
- FloodfillBoxClass * m_Prev;
- FloodfillBoxClass * m_Next;
- PathfindSectorClass * m_Sector;
- float m_MinZPos;
- float m_MaxZPos;
- Vector3 m_Position;
- FloodfillBoxClass * m_GridLink;
- //////////////////////////////////////////////////////////////////////
- // Static member data
- //////////////////////////////////////////////////////////////////////
- static FloodfillBoxClass * m_First;
- static FloodfillBoxClass * m_Last;
- };
- //////////////////////////////////////////////////////////////////////////
- // Find_Relative
- //////////////////////////////////////////////////////////////////////////
- inline FloodfillBoxClass *
- FloodfillBoxClass::Find_Relative (int cx, int cy)
- {
- PATHFIND_DIR x_dir = DIR_RIGHT;
- PATHFIND_DIR y_dir = DIR_BACKWARD;
- if (cx < 0) {
- x_dir = DIR_LEFT;
- cx = -cx;
- }
- if (cy < 0) {
- y_dir = DIR_FORWARD;
- cy = -cy;
- }
- FloodfillBoxClass *curr_box = this;
- for (int x = 0; x < cx; x ++) {
- curr_box = curr_box->Peek_Neighbor (x_dir);
- }
- for (int y = 0; y < cy; y ++) {
- curr_box = curr_box->Peek_Neighbor (y_dir);
- }
- return curr_box;
- }
- //////////////////////////////////////////////////////////////////////////
- // Remove
- //////////////////////////////////////////////////////////////////////////
- inline void
- FloodfillBoxClass::Remove (void)
- {
- if (m_Prev) {
- m_Prev->m_Next = m_Next;
- }
-
- if (m_Next) {
- m_Next->m_Prev = m_Prev;
- }
-
- if (m_First == this) {
- m_First = m_Next;
- }
- if (m_Last == this) {
- m_Last = m_Prev;
- }
-
- m_Prev = NULL;
- m_Next = NULL;
- return ;
- }
- //////////////////////////////////////////////////////////////////////////
- // Add
- //////////////////////////////////////////////////////////////////////////
- inline void
- FloodfillBoxClass::Add (FloodfillBoxClass *new_obj)
- {
- if (m_Last == NULL) {
- m_First = new_obj;
- } else {
- m_Last->m_Next = new_obj;
- new_obj->m_Prev = m_Last;
- }
- m_Last = new_obj;
- return ;
- }
- //////////////////////////////////////////////////////////////////////////
- // Unlink
- //////////////////////////////////////////////////////////////////////////
- inline void
- FloodfillBoxClass::Unlink (void)
- {
- Remove ();
- if (m_Neighbors[DIR_FORWARD] != NULL) {
- m_Neighbors[DIR_FORWARD]->Set_Neighbor (DIR_BACKWARD, NULL, false);
- }
- if (m_Neighbors[DIR_BACKWARD] != NULL) {
- m_Neighbors[DIR_BACKWARD]->Set_Neighbor (DIR_FORWARD, NULL, false);
- }
- if (m_Neighbors[DIR_LEFT] != NULL) {
- m_Neighbors[DIR_LEFT]->Set_Neighbor (DIR_RIGHT, NULL, false);
- }
- if (m_Neighbors[DIR_RIGHT] != NULL) {
- m_Neighbors[DIR_RIGHT]->Set_Neighbor (DIR_LEFT, NULL, false);
- }
- return ;
- }
- //////////////////////////////////////////////////////////////////////////
- // Is_Edge
- //////////////////////////////////////////////////////////////////////////
- inline bool
- FloodfillBoxClass::Is_Edge (void)
- {
- bool retval = false;
- if (Peek_Neighbor (DIR_FORWARD) == NULL ||
- Peek_Neighbor (DIR_BACKWARD) == NULL ||
- Peek_Neighbor (DIR_LEFT) == NULL ||
- Peek_Neighbor (DIR_RIGHT) == NULL) {
-
- retval = true;
- }
- return retval;
- }
- //////////////////////////////////////////////////////////////////////////
- // Are_Neighbors_Processed
- //////////////////////////////////////////////////////////////////////////
- inline bool
- FloodfillBoxClass::Are_Neighbors_Processed (void)
- {
- bool retval = true;
- for (int index = 0; (index < 4) && retval; index ++) {
- if ((m_Neighbors[0] != NULL) && m_Neighbors[0]->Needs_Processing ()) {
- retval = false;
- }
- }
- return retval;
- }
- //////////////////////////////////////////////////////////////////////////
- // Set_Neighbor
- //////////////////////////////////////////////////////////////////////////
- inline void
- FloodfillBoxClass::Set_Neighbor (PATHFIND_DIR dir, FloodfillBoxClass *obj, bool traversible)
- {
- m_Neighbors[dir] = obj;
- Set_Traversible (dir, traversible);
- return ;
- }
- //////////////////////////////////////////////////////////////////////////
- // Peek_Neighbor
- //////////////////////////////////////////////////////////////////////////
- inline FloodfillBoxClass *
- FloodfillBoxClass::Peek_Neighbor (PATHFIND_DIR dir, bool only_traversible)
- {
- FloodfillBoxClass *neighbor = NULL;
- if ((only_traversible == false) || Get_Traversible (dir)) {
- neighbor = m_Neighbors[dir];
- }
- return neighbor;
- }
- //////////////////////////////////////////////////////////////////////////
- // Set_Flag
- //////////////////////////////////////////////////////////////////////////
- inline void
- FloodfillBoxClass::Set_Flag (uint8 flag, bool value)
- {
- m_Flags &= ~flag;
- if (value) {
- m_Flags |= flag;
- }
- return ;
- }
- //////////////////////////////////////////////////////////////////////////
- // Set_Traversible
- //////////////////////////////////////////////////////////////////////////
- inline void
- FloodfillBoxClass::Set_Traversible (PATHFIND_DIR dir, bool onoff)
- {
- if (onoff) {
- m_DirectionInfo |= (1 << dir);
- } else {
- m_DirectionInfo &= ~(1 << dir);
- }
- return ;
- }
- //////////////////////////////////////////////////////////////////////////
- // Get_Traversible
- //////////////////////////////////////////////////////////////////////////
- inline bool
- FloodfillBoxClass::Get_Traversible (PATHFIND_DIR dir)
- {
- int bit = (1 << dir);
- return (m_DirectionInfo & bit) == bit;
- }
- //////////////////////////////////////////////////////////////////////////
- // Part_Of_Portal
- //////////////////////////////////////////////////////////////////////////
- inline void
- FloodfillBoxClass::Part_Of_Portal (PATHFIND_DIR dir, bool onoff)
- {
- if (onoff) {
- m_DirectionInfo |= (1 << (dir + 4));
- } else {
- m_DirectionInfo &= ~(1 << (dir + 4));
- }
- return ;
- }
- //////////////////////////////////////////////////////////////////////////
- // Part_Of_Portal
- //////////////////////////////////////////////////////////////////////////
- inline bool
- FloodfillBoxClass::Part_Of_Portal (PATHFIND_DIR dir)
- {
- int bit = (1 << (dir + 4));
- return (m_DirectionInfo & bit) == bit;
- }
- #endif //__FLOODFILLBOX_H
|