168 lines
6.8 KiB
C++
168 lines
6.8 KiB
C++
//========= Copyright Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose:
|
|
//
|
|
// $NoKeywords: $
|
|
//
|
|
//=============================================================================//
|
|
// nav_node.h
|
|
// Navigation Nodes are used when generating a Navigation Mesh by point sampling
|
|
// the map Author: Michael S. Booth (mike@turtlerockstudios.com), January 2003
|
|
|
|
#ifndef _NAV_NODE_H_
|
|
#define _NAV_NODE_H_
|
|
|
|
#include "nav.h"
|
|
|
|
// If DEBUG_NAV_NODES is true, nav_show_nodes controls drawing node positions,
|
|
// and nav_show_node_id allows you to show the IDs of nodes that didn't get used
|
|
// to create areas.
|
|
#define DEBUG_NAV_NODES 1
|
|
|
|
//--------------------------------------------------------------------------------------------------------------
|
|
/**
|
|
* Navigation Nodes.
|
|
* These Nodes encapsulate world locations, and ways to get from one location to
|
|
* an adjacent one. Note that these links are not necessarily commutative
|
|
* (falling off of a ledge, for example).
|
|
*/
|
|
class CNavNode {
|
|
public:
|
|
CNavNode(const Vector &pos, const Vector &normal, CNavNode *parent,
|
|
bool onDisplacement);
|
|
~CNavNode();
|
|
|
|
static CNavNode *GetNode(
|
|
const Vector &pos); ///< return navigation node at the position, or
|
|
///< NULL if none exists
|
|
static void CleanupGeneration();
|
|
|
|
CNavNode *GetConnectedNode(
|
|
NavDirType dir) const; ///< get navigation node connected in given
|
|
///< direction, or NULL if cant go that way
|
|
const Vector *GetPosition(void) const;
|
|
const Vector *GetNormal(void) const { return &m_normal; }
|
|
unsigned int GetID(void) const { return m_id; }
|
|
|
|
static CNavNode *GetFirst(void) { return m_list; }
|
|
static unsigned int GetListLength(void) { return m_listLength; }
|
|
CNavNode *GetNext(void) { return m_next; }
|
|
|
|
void Draw(void);
|
|
|
|
void ConnectTo(
|
|
CNavNode *node, NavDirType dir, float obstacleHeight,
|
|
float flObstacleStartDist,
|
|
float flObstacleEndDist); ///< create a connection FROM this node TO
|
|
///< the given node, in the given direction
|
|
CNavNode *GetParent(void) const;
|
|
|
|
void MarkAsVisited(
|
|
NavDirType dir); ///< mark the given direction as having been visited
|
|
BOOL HasVisited(NavDirType dir); ///< return TRUE if the given direction
|
|
///< has already been searched
|
|
BOOL IsBiLinked(
|
|
NavDirType dir) const; ///< node is bidirectionally linked to another
|
|
///< node in the given direction
|
|
BOOL IsClosedCell(
|
|
void) const; ///< node is the NW corner of a bi-linked quad of nodes
|
|
|
|
void Cover(void) {
|
|
m_isCovered = true;
|
|
} ///< @todo Should pass in area that is covering
|
|
BOOL IsCovered(void) const {
|
|
return m_isCovered;
|
|
} ///< return true if this node has been covered by an area
|
|
|
|
void AssignArea(CNavArea *area); ///< assign the given area to this node
|
|
CNavArea *GetArea(void) const; ///< return associated area
|
|
|
|
void SetAttributes(int bits) { m_attributeFlags = bits; }
|
|
int GetAttributes(void) const { return m_attributeFlags; }
|
|
float GetGroundHeightAboveNode(NavCornerType cornerType)
|
|
const; ///< return ground height above node in given corner direction
|
|
///< (NUM_CORNERS for highest in any direction)
|
|
bool IsBlockedInAnyDirection(
|
|
void) const; ///< return true if the node is blocked in any direction
|
|
|
|
bool IsOnDisplacement(void) const { return m_isOnDisplacement; }
|
|
|
|
private:
|
|
CNavNode() {} // constructor used only for hash lookup
|
|
friend class CNavMesh;
|
|
|
|
bool TestForCrouchArea(NavCornerType cornerNum, const Vector &mins,
|
|
const Vector &maxs, float *groundHeightAboveNode);
|
|
void CheckCrouch(void);
|
|
|
|
Vector m_pos; ///< position of this node in the world
|
|
Vector m_normal; ///< surface normal at this location
|
|
CNavNode *m_to[NUM_DIRECTIONS]; ///< links to north, south, east, and west.
|
|
///< NULL if no link
|
|
float m_obstacleHeight[NUM_DIRECTIONS]; ///< obstacle height (delta from
|
|
///< nav node z position) that must
|
|
///< be climbed to reach next node
|
|
///< in this direction
|
|
float m_obstacleStartDist[NUM_DIRECTIONS]; ///< distance along this
|
|
///< direction to reach the
|
|
///< beginning of the obstacle
|
|
float m_obstacleEndDist[NUM_DIRECTIONS]; ///< distance along this direction
|
|
///< to reach the end of the
|
|
///< obstacle
|
|
unsigned int m_id; ///< unique ID of this node
|
|
int m_attributeFlags; ///< set of attribute bit flags (see
|
|
///< NavAttributeType)
|
|
|
|
static CNavNode *m_list; ///< the master list of all nodes for this map
|
|
static unsigned int m_listLength;
|
|
static unsigned int m_nextID;
|
|
CNavNode *m_next; ///< next link in master list
|
|
CNavNode *m_nextAtXY; ///< next link at a particular position
|
|
|
|
// below are only needed when generating
|
|
unsigned char
|
|
m_visited; ///< flags for automatic node generation. If direction bit
|
|
///< is clear, that direction hasn't been explored yet.
|
|
CNavNode *m_parent; ///< the node prior to this in the search, which we pop
|
|
///< back to when this node's search is done (a stack)
|
|
bool m_isCovered; ///< true when this node is "covered" by a CNavArea
|
|
CNavArea *m_area; ///< the area this node is contained within
|
|
|
|
bool m_isBlocked[NUM_CORNERS];
|
|
bool m_crouch[NUM_CORNERS];
|
|
float m_groundHeightAboveNode[NUM_CORNERS];
|
|
bool m_isOnDisplacement;
|
|
};
|
|
|
|
//--------------------------------------------------------------------------------------------------------------
|
|
//
|
|
// Inlines
|
|
//
|
|
|
|
inline CNavNode *CNavNode::GetConnectedNode(NavDirType dir) const {
|
|
return m_to[dir];
|
|
}
|
|
|
|
inline const Vector *CNavNode::GetPosition(void) const { return &m_pos; }
|
|
|
|
inline CNavNode *CNavNode::GetParent(void) const { return m_parent; }
|
|
|
|
inline void CNavNode::MarkAsVisited(NavDirType dir) { m_visited |= (1 << dir); }
|
|
|
|
inline BOOL CNavNode::HasVisited(NavDirType dir) {
|
|
if (m_visited & (1 << dir)) return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
inline void CNavNode::AssignArea(CNavArea *area) { m_area = area; }
|
|
|
|
inline CNavArea *CNavNode::GetArea(void) const { return m_area; }
|
|
|
|
inline bool CNavNode::IsBlockedInAnyDirection(void) const {
|
|
return m_isBlocked[SOUTH_EAST] || m_isBlocked[SOUTH_WEST] ||
|
|
m_isBlocked[NORTH_EAST] || m_isBlocked[NORTH_WEST];
|
|
}
|
|
|
|
#endif // _NAV_NODE_H_
|