TrinityCore
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
DetourNavMeshBuilder.cpp File Reference
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <float.h>
#include "DetourNavMesh.h"
#include "DetourCommon.h"
#include "DetourMath.h"
#include "DetourNavMeshBuilder.h"
#include "DetourAlloc.h"
#include "DetourAssert.h"
+ Include dependency graph for DetourNavMeshBuilder.cpp:

Classes

struct  BVItem
 

Functions

static int compareItemX (const void *va, const void *vb)
 
static int compareItemY (const void *va, const void *vb)
 
static int compareItemZ (const void *va, const void *vb)
 
static void calcExtends (BVItem *items, const int, const int imin, const int imax, unsigned short *bmin, unsigned short *bmax)
 
int longestAxis (unsigned short x, unsigned short y, unsigned short z)
 
static void subdivide (BVItem *items, int nitems, int imin, int imax, int &curNode, dtBVNode *nodes)
 
static int createBVTree (const unsigned short *verts, const int, const unsigned short *polys, const int npolys, const int nvp, const float cs, const float ch, const int, dtBVNode *nodes)
 
static unsigned char classifyOffMeshPoint (const float *pt, const float *bmin, const float *bmax)
 
bool dtCreateNavMeshData (dtNavMeshCreateParams *params, unsigned char **outData, int *outDataSize)
 
bool dtNavMeshHeaderSwapEndian (unsigned char *data, const int)
 
bool dtNavMeshDataSwapEndian (unsigned char *data, const int)
 

Variables

static unsigned short MESH_NULL_IDX = 0xffff
 

Function Documentation

static void calcExtends ( BVItem items,
const int  ,
const int  imin,
const int  imax,
unsigned short *  bmin,
unsigned short *  bmax 
)
static
75 {
76  bmin[0] = items[imin].bmin[0];
77  bmin[1] = items[imin].bmin[1];
78  bmin[2] = items[imin].bmin[2];
79 
80  bmax[0] = items[imin].bmax[0];
81  bmax[1] = items[imin].bmax[1];
82  bmax[2] = items[imin].bmax[2];
83 
84  for (int i = imin+1; i < imax; ++i)
85  {
86  const BVItem& it = items[i];
87  if (it.bmin[0] < bmin[0]) bmin[0] = it.bmin[0];
88  if (it.bmin[1] < bmin[1]) bmin[1] = it.bmin[1];
89  if (it.bmin[2] < bmin[2]) bmin[2] = it.bmin[2];
90 
91  if (it.bmax[0] > bmax[0]) bmax[0] = it.bmax[0];
92  if (it.bmax[1] > bmax[1]) bmax[1] = it.bmax[1];
93  if (it.bmax[2] > bmax[2]) bmax[2] = it.bmax[2];
94  }
95 }
unsigned short bmax[3]
Definition: DetourNavMeshBuilder.cpp:36
unsigned short bmin[3]
Definition: DetourNavMeshBuilder.cpp:35
Definition: DetourNavMeshBuilder.cpp:33

+ Here is the caller graph for this function:

static unsigned char classifyOffMeshPoint ( const float *  pt,
const float *  bmin,
const float *  bmax 
)
static
218 {
219  static const unsigned char XP = 1<<0;
220  static const unsigned char ZP = 1<<1;
221  static const unsigned char XM = 1<<2;
222  static const unsigned char ZM = 1<<3;
223 
224  unsigned char outcode = 0;
225  outcode |= (pt[0] >= bmax[0]) ? XP : 0;
226  outcode |= (pt[2] >= bmax[2]) ? ZP : 0;
227  outcode |= (pt[0] < bmin[0]) ? XM : 0;
228  outcode |= (pt[2] < bmin[2]) ? ZM : 0;
229 
230  switch (outcode)
231  {
232  case XP: return 0;
233  case XP|ZP: return 1;
234  case ZP: return 2;
235  case XM|ZP: return 3;
236  case XM: return 4;
237  case XM|ZM: return 5;
238  case ZM: return 6;
239  case XP|ZM: return 7;
240  };
241 
242  return 0xff;
243 }

+ Here is the caller graph for this function:

static int compareItemX ( const void *  va,
const void *  vb 
)
static
41 {
42  const BVItem* a = (const BVItem*)va;
43  const BVItem* b = (const BVItem*)vb;
44  if (a->bmin[0] < b->bmin[0])
45  return -1;
46  if (a->bmin[0] > b->bmin[0])
47  return 1;
48  return 0;
49 }
unsigned short bmin[3]
Definition: DetourNavMeshBuilder.cpp:35
Definition: DetourNavMeshBuilder.cpp:33

+ Here is the caller graph for this function:

static int compareItemY ( const void *  va,
const void *  vb 
)
static
52 {
53  const BVItem* a = (const BVItem*)va;
54  const BVItem* b = (const BVItem*)vb;
55  if (a->bmin[1] < b->bmin[1])
56  return -1;
57  if (a->bmin[1] > b->bmin[1])
58  return 1;
59  return 0;
60 }
unsigned short bmin[3]
Definition: DetourNavMeshBuilder.cpp:35
Definition: DetourNavMeshBuilder.cpp:33

+ Here is the caller graph for this function:

static int compareItemZ ( const void *  va,
const void *  vb 
)
static
63 {
64  const BVItem* a = (const BVItem*)va;
65  const BVItem* b = (const BVItem*)vb;
66  if (a->bmin[2] < b->bmin[2])
67  return -1;
68  if (a->bmin[2] > b->bmin[2])
69  return 1;
70  return 0;
71 }
unsigned short bmin[3]
Definition: DetourNavMeshBuilder.cpp:35
Definition: DetourNavMeshBuilder.cpp:33

+ Here is the caller graph for this function:

static int createBVTree ( const unsigned short *  verts,
const int  ,
const unsigned short *  polys,
const int  npolys,
const int  nvp,
const float  cs,
const float  ch,
const int  ,
dtBVNode nodes 
)
static
176 {
177  // Build tree
178  BVItem* items = (BVItem*)dtAlloc(sizeof(BVItem)*npolys, DT_ALLOC_TEMP);
179  for (int i = 0; i < npolys; i++)
180  {
181  BVItem& it = items[i];
182  it.i = i;
183  // Calc polygon bounds.
184  const unsigned short* p = &polys[i*nvp*2];
185  it.bmin[0] = it.bmax[0] = verts[p[0]*3+0];
186  it.bmin[1] = it.bmax[1] = verts[p[0]*3+1];
187  it.bmin[2] = it.bmax[2] = verts[p[0]*3+2];
188 
189  for (int j = 1; j < nvp; ++j)
190  {
191  if (p[j] == MESH_NULL_IDX) break;
192  unsigned short x = verts[p[j]*3+0];
193  unsigned short y = verts[p[j]*3+1];
194  unsigned short z = verts[p[j]*3+2];
195 
196  if (x < it.bmin[0]) it.bmin[0] = x;
197  if (y < it.bmin[1]) it.bmin[1] = y;
198  if (z < it.bmin[2]) it.bmin[2] = z;
199 
200  if (x > it.bmax[0]) it.bmax[0] = x;
201  if (y > it.bmax[1]) it.bmax[1] = y;
202  if (z > it.bmax[2]) it.bmax[2] = z;
203  }
204  // Remap y
205  it.bmin[1] = (unsigned short)dtMathFloorf((float)it.bmin[1]*ch/cs);
206  it.bmax[1] = (unsigned short)dtMathCeilf((float)it.bmax[1]*ch/cs);
207  }
208 
209  int curNode = 0;
210  subdivide(items, npolys, 0, npolys, curNode, nodes);
211 
212  dtFree(items);
213 
214  return curNode;
215 }
void * dtAlloc(int size, dtAllocHint hint)
Definition: DetourAlloc.cpp:41
float dtMathCeilf(float x)
Definition: DetourMath.h:15
static unsigned short MESH_NULL_IDX
Definition: DetourNavMeshBuilder.cpp:30
unsigned short bmax[3]
Definition: DetourNavMeshBuilder.cpp:36
int i
Definition: DetourNavMeshBuilder.cpp:37
unsigned short bmin[3]
Definition: DetourNavMeshBuilder.cpp:35
G3D::int16 z
Definition: Vector3int16.h:46
G3D::int16 y
Definition: Vector2int16.h:38
Memory used temporarily within a function.
Definition: DetourAlloc.h:27
float dtMathFloorf(float x)
Definition: DetourMath.h:14
static void subdivide(BVItem *items, int nitems, int imin, int imax, int &curNode, dtBVNode *nodes)
Definition: DetourNavMeshBuilder.cpp:114
G3D::int16 x
Definition: Vector2int16.h:37
Definition: DetourNavMeshBuilder.cpp:33
void dtFree(void *ptr)
Definition: DetourAlloc.cpp:46

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

bool dtNavMeshDataSwapEndian ( unsigned char *  data,
const int   
)
Warning
This function assumes that the header is in the correct endianess already. Call dtNavMeshHeaderSwapEndian() first on the data if the data is expected to be in wrong endianess to start with. Call dtNavMeshHeaderSwapEndian() after the data has been swapped if converting from native to foreign endianess.
688 {
689  // Make sure the data is in right format.
690  dtMeshHeader* header = (dtMeshHeader*)data;
691  if (header->magic != DT_NAVMESH_MAGIC)
692  return false;
693  if (header->version != DT_NAVMESH_VERSION)
694  return false;
695 
696  // Patch header pointers.
697  const int headerSize = dtAlign4(sizeof(dtMeshHeader));
698  const int vertsSize = dtAlign4(sizeof(float)*3*header->vertCount);
699  const int polysSize = dtAlign4(sizeof(dtPoly)*header->polyCount);
700  const int linksSize = dtAlign4(sizeof(dtLink)*(header->maxLinkCount));
701  const int detailMeshesSize = dtAlign4(sizeof(dtPolyDetail)*header->detailMeshCount);
702  const int detailVertsSize = dtAlign4(sizeof(float)*3*header->detailVertCount);
703  const int detailTrisSize = dtAlign4(sizeof(unsigned char)*4*header->detailTriCount);
704  const int bvtreeSize = dtAlign4(sizeof(dtBVNode)*header->bvNodeCount);
705  const int offMeshLinksSize = dtAlign4(sizeof(dtOffMeshConnection)*header->offMeshConCount);
706 
707  unsigned char* d = data + headerSize;
708  float* verts = (float*)d; d += vertsSize;
709  dtPoly* polys = (dtPoly*)d; d += polysSize;
710  /*dtLink* links = (dtLink*)d;*/ d += linksSize;
711  dtPolyDetail* detailMeshes = (dtPolyDetail*)d; d += detailMeshesSize;
712  float* detailVerts = (float*)d; d += detailVertsSize;
713  /*unsigned char* detailTris = (unsigned char*)d;*/ d += detailTrisSize;
714  dtBVNode* bvTree = (dtBVNode*)d; d += bvtreeSize;
715  dtOffMeshConnection* offMeshCons = (dtOffMeshConnection*)d; d += offMeshLinksSize;
716 
717  // Vertices
718  for (int i = 0; i < header->vertCount*3; ++i)
719  {
720  dtSwapEndian(&verts[i]);
721  }
722 
723  // Polys
724  for (int i = 0; i < header->polyCount; ++i)
725  {
726  dtPoly* p = &polys[i];
727  // poly->firstLink is update when tile is added, no need to swap.
728  for (int j = 0; j < DT_VERTS_PER_POLYGON; ++j)
729  {
730  dtSwapEndian(&p->verts[j]);
731  dtSwapEndian(&p->neis[j]);
732  }
733  dtSwapEndian(&p->flags);
734  }
735 
736  // Links are rebuild when tile is added, no need to swap.
737 
738  // Detail meshes
739  for (int i = 0; i < header->detailMeshCount; ++i)
740  {
741  dtPolyDetail* pd = &detailMeshes[i];
742  dtSwapEndian(&pd->vertBase);
743  dtSwapEndian(&pd->triBase);
744  }
745 
746  // Detail verts
747  for (int i = 0; i < header->detailVertCount*3; ++i)
748  {
749  dtSwapEndian(&detailVerts[i]);
750  }
751 
752  // BV-tree
753  for (int i = 0; i < header->bvNodeCount; ++i)
754  {
755  dtBVNode* node = &bvTree[i];
756  for (int j = 0; j < 3; ++j)
757  {
758  dtSwapEndian(&node->bmin[j]);
759  dtSwapEndian(&node->bmax[j]);
760  }
761  dtSwapEndian(&node->i);
762  }
763 
764  // Off-mesh Connections.
765  for (int i = 0; i < header->offMeshConCount; ++i)
766  {
767  dtOffMeshConnection* con = &offMeshCons[i];
768  for (int j = 0; j < 6; ++j)
769  dtSwapEndian(&con->pos[j]);
770  dtSwapEndian(&con->rad);
771  dtSwapEndian(&con->poly);
772  }
773 
774  return true;
775 }
void dtSwapEndian(unsigned short *v)
Definition: DetourCommon.h:452
unsigned short poly
The polygon reference of the connection within the tile.
Definition: DetourNavMesh.h:231
unsigned short bmax[3]
Maximum bounds of the node's AABB. [(x, y, z)].
Definition: DetourNavMesh.h:216
Defines the location of detail sub-mesh data within a dtMeshTile.
Definition: DetourNavMesh.h:189
unsigned short flags
The user defined polygon flags.
Definition: DetourNavMesh.h:166
int offMeshConCount
The number of off-mesh connections.
Definition: DetourNavMesh.h:265
int detailMeshCount
The number of sub-meshes in the detail mesh.
Definition: DetourNavMesh.h:258
unsigned short verts[DT_VERTS_PER_POLYGON]
Definition: DetourNavMesh.h:160
int i
The node's index. (Negative for escape sequence.)
Definition: DetourNavMesh.h:217
Definition: DetourNavMesh.h:213
unsigned int vertBase
The offset of the vertices in the dtMeshTile::detailVerts array.
Definition: DetourNavMesh.h:191
unsigned short bmin[3]
Minimum bounds of the node's AABB. [(x, y, z)].
Definition: DetourNavMesh.h:215
Definition: DetourNavMesh.h:247
unsigned short neis[DT_VERTS_PER_POLYGON]
Packed data representing neighbor polygons references and flags for each edge.
Definition: DetourNavMesh.h:163
Definition: DetourNavMesh.h:153
float rad
The radius of the endpoints. [Limit: >= 0].
Definition: DetourNavMesh.h:228
int polyCount
The number of polygons in the tile.
Definition: DetourNavMesh.h:255
int bvNodeCount
The number of bounding volume nodes. (Zero if bounding volumes are disabled.)
Definition: DetourNavMesh.h:264
int version
Tile data format version number.
Definition: DetourNavMesh.h:250
int detailVertCount
The number of unique vertices in the detail mesh. (In addition to the polygon vertices.)
Definition: DetourNavMesh.h:261
int maxLinkCount
The number of allocated links.
Definition: DetourNavMesh.h:257
int magic
Tile magic number. (Used to identify the data format.)
Definition: DetourNavMesh.h:249
int dtAlign4(int x)
Definition: DetourCommon.h:441
int detailTriCount
The number of triangles in the detail mesh.
Definition: DetourNavMesh.h:263
unsigned int triBase
The offset of the triangles in the dtMeshTile::detailTris array.
Definition: DetourNavMesh.h:192
static const int DT_NAVMESH_MAGIC
A magic number used to detect compatibility of navigation tile data.
Definition: DetourNavMesh.h:66
float pos[6]
The endpoints of the connection. [(ax, ay, az, bx, by, bz)].
Definition: DetourNavMesh.h:225
static const int DT_NAVMESH_VERSION
A version number used to detect compatibility of navigation tile data.
Definition: DetourNavMesh.h:69
int vertCount
The number of vertices in the tile.
Definition: DetourNavMesh.h:256
Definition: DetourNavMesh.h:222
static const int DT_VERTS_PER_POLYGON
Definition: DetourNavMesh.h:57

+ Here is the call graph for this function:

bool dtNavMeshHeaderSwapEndian ( unsigned char *  data,
const int  dataSize 
)

Swaps the endianess of the tile data's header (dtMeshHeader).

Parameters
[in,out]dataThe tile data array.
[in]dataSizeThe size of the data array.
636 {
637  dtMeshHeader* header = (dtMeshHeader*)data;
638 
639  int swappedMagic = DT_NAVMESH_MAGIC;
640  int swappedVersion = DT_NAVMESH_VERSION;
641  dtSwapEndian(&swappedMagic);
642  dtSwapEndian(&swappedVersion);
643 
644  if ((header->magic != DT_NAVMESH_MAGIC || header->version != DT_NAVMESH_VERSION) &&
645  (header->magic != swappedMagic || header->version != swappedVersion))
646  {
647  return false;
648  }
649 
650  dtSwapEndian(&header->magic);
651  dtSwapEndian(&header->version);
652  dtSwapEndian(&header->x);
653  dtSwapEndian(&header->y);
654  dtSwapEndian(&header->layer);
655  dtSwapEndian(&header->userId);
656  dtSwapEndian(&header->polyCount);
657  dtSwapEndian(&header->vertCount);
658  dtSwapEndian(&header->maxLinkCount);
659  dtSwapEndian(&header->detailMeshCount);
660  dtSwapEndian(&header->detailVertCount);
661  dtSwapEndian(&header->detailTriCount);
662  dtSwapEndian(&header->bvNodeCount);
663  dtSwapEndian(&header->offMeshConCount);
664  dtSwapEndian(&header->offMeshBase);
665  dtSwapEndian(&header->walkableHeight);
666  dtSwapEndian(&header->walkableRadius);
667  dtSwapEndian(&header->walkableClimb);
668  dtSwapEndian(&header->bmin[0]);
669  dtSwapEndian(&header->bmin[1]);
670  dtSwapEndian(&header->bmin[2]);
671  dtSwapEndian(&header->bmax[0]);
672  dtSwapEndian(&header->bmax[1]);
673  dtSwapEndian(&header->bmax[2]);
674  dtSwapEndian(&header->bvQuantFactor);
675 
676  // Freelist index and pointers are updated when tile is added, no need to swap.
677 
678  return true;
679 }
void dtSwapEndian(unsigned short *v)
Definition: DetourCommon.h:452
float walkableHeight
The height of the agents using the tile.
Definition: DetourNavMesh.h:267
float walkableClimb
The maximum climb height of the agents using the tile.
Definition: DetourNavMesh.h:269
float walkableRadius
The radius of the agents using the tile.
Definition: DetourNavMesh.h:268
float bvQuantFactor
The bounding volume quantization factor.
Definition: DetourNavMesh.h:274
int offMeshConCount
The number of off-mesh connections.
Definition: DetourNavMesh.h:265
float bmax[3]
The maximum bounds of the tile's AABB. [(x, y, z)].
Definition: DetourNavMesh.h:271
int detailMeshCount
The number of sub-meshes in the detail mesh.
Definition: DetourNavMesh.h:258
int offMeshBase
The index of the first polygon which is an off-mesh connection.
Definition: DetourNavMesh.h:266
int layer
The layer of the tile within the dtNavMesh tile grid. (x, y, layer)
Definition: DetourNavMesh.h:253
Definition: DetourNavMesh.h:247
int polyCount
The number of polygons in the tile.
Definition: DetourNavMesh.h:255
int bvNodeCount
The number of bounding volume nodes. (Zero if bounding volumes are disabled.)
Definition: DetourNavMesh.h:264
int x
The x-position of the tile within the dtNavMesh tile grid. (x, y, layer)
Definition: DetourNavMesh.h:251
float bmin[3]
The minimum bounds of the tile's AABB. [(x, y, z)].
Definition: DetourNavMesh.h:270
int version
Tile data format version number.
Definition: DetourNavMesh.h:250
int detailVertCount
The number of unique vertices in the detail mesh. (In addition to the polygon vertices.)
Definition: DetourNavMesh.h:261
int maxLinkCount
The number of allocated links.
Definition: DetourNavMesh.h:257
unsigned int userId
The user defined id of the tile.
Definition: DetourNavMesh.h:254
int magic
Tile magic number. (Used to identify the data format.)
Definition: DetourNavMesh.h:249
int detailTriCount
The number of triangles in the detail mesh.
Definition: DetourNavMesh.h:263
static const int DT_NAVMESH_MAGIC
A magic number used to detect compatibility of navigation tile data.
Definition: DetourNavMesh.h:66
int y
The y-position of the tile within the dtNavMesh tile grid. (x, y, layer)
Definition: DetourNavMesh.h:252
static const int DT_NAVMESH_VERSION
A version number used to detect compatibility of navigation tile data.
Definition: DetourNavMesh.h:69
int vertCount
The number of vertices in the tile.
Definition: DetourNavMesh.h:256

+ Here is the call graph for this function:

int longestAxis ( unsigned short  x,
unsigned short  y,
unsigned short  z 
)
inline
98 {
99  int axis = 0;
100  unsigned short maxVal = x;
101  if (y > maxVal)
102  {
103  axis = 1;
104  maxVal = y;
105  }
106  if (z > maxVal)
107  {
108  axis = 2;
109  maxVal = z;
110  }
111  return axis;
112 }
G3D::int16 z
Definition: Vector3int16.h:46
G3D::int16 y
Definition: Vector2int16.h:38
G3D::int16 x
Definition: Vector2int16.h:37

+ Here is the caller graph for this function:

static void subdivide ( BVItem items,
int  nitems,
int  imin,
int  imax,
int &  curNode,
dtBVNode nodes 
)
static
115 {
116  int inum = imax - imin;
117  int icur = curNode;
118 
119  dtBVNode& node = nodes[curNode++];
120 
121  if (inum == 1)
122  {
123  // Leaf
124  node.bmin[0] = items[imin].bmin[0];
125  node.bmin[1] = items[imin].bmin[1];
126  node.bmin[2] = items[imin].bmin[2];
127 
128  node.bmax[0] = items[imin].bmax[0];
129  node.bmax[1] = items[imin].bmax[1];
130  node.bmax[2] = items[imin].bmax[2];
131 
132  node.i = items[imin].i;
133  }
134  else
135  {
136  // Split
137  calcExtends(items, nitems, imin, imax, node.bmin, node.bmax);
138 
139  int axis = longestAxis(node.bmax[0] - node.bmin[0],
140  node.bmax[1] - node.bmin[1],
141  node.bmax[2] - node.bmin[2]);
142 
143  if (axis == 0)
144  {
145  // Sort along x-axis
146  qsort(items+imin, inum, sizeof(BVItem), compareItemX);
147  }
148  else if (axis == 1)
149  {
150  // Sort along y-axis
151  qsort(items+imin, inum, sizeof(BVItem), compareItemY);
152  }
153  else
154  {
155  // Sort along z-axis
156  qsort(items+imin, inum, sizeof(BVItem), compareItemZ);
157  }
158 
159  int isplit = imin+inum/2;
160 
161  // Left
162  subdivide(items, nitems, imin, isplit, curNode, nodes);
163  // Right
164  subdivide(items, nitems, isplit, imax, curNode, nodes);
165 
166  int iescape = curNode - icur;
167  // Negative index means escape.
168  node.i = -iescape;
169  }
170 }
unsigned short bmax[3]
Maximum bounds of the node's AABB. [(x, y, z)].
Definition: DetourNavMesh.h:216
static int compareItemX(const void *va, const void *vb)
Definition: DetourNavMeshBuilder.cpp:40
unsigned short bmax[3]
Definition: DetourNavMeshBuilder.cpp:36
int i
The node's index. (Negative for escape sequence.)
Definition: DetourNavMesh.h:217
Definition: DetourNavMesh.h:213
unsigned short bmin[3]
Minimum bounds of the node's AABB. [(x, y, z)].
Definition: DetourNavMesh.h:215
static void calcExtends(BVItem *items, const int, const int imin, const int imax, unsigned short *bmin, unsigned short *bmax)
Definition: DetourNavMeshBuilder.cpp:73
int i
Definition: DetourNavMeshBuilder.cpp:37
unsigned short bmin[3]
Definition: DetourNavMeshBuilder.cpp:35
static int compareItemZ(const void *va, const void *vb)
Definition: DetourNavMeshBuilder.cpp:62
int longestAxis(unsigned short x, unsigned short y, unsigned short z)
Definition: DetourNavMeshBuilder.cpp:97
static void subdivide(BVItem *items, int nitems, int imin, int imax, int &curNode, dtBVNode *nodes)
Definition: DetourNavMeshBuilder.cpp:114
Definition: DetourNavMeshBuilder.cpp:33
static int compareItemY(const void *va, const void *vb)
Definition: DetourNavMeshBuilder.cpp:51

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

Variable Documentation

unsigned short MESH_NULL_IDX = 0xffff
static