bool dtProximityGrid::init(const int poolSize, const float cellSize) { dtAssert(poolSize > 0); dtAssert(cellSize > 0.0f); m_cellSize = cellSize; m_invCellSize = 1.0f / m_cellSize; // Allocate hashs buckets m_bucketsSize = dtNextPow2(poolSize); m_buckets = (unsigned short*)dtAlloc(sizeof(unsigned short)*m_bucketsSize, DT_ALLOC_PERM); if (!m_buckets) return false; // Allocate pool of items. m_poolSize = poolSize; m_poolHead = 0; m_pool = (Item*)dtAlloc(sizeof(Item)*m_poolSize, DT_ALLOC_PERM); if (!m_pool) return false; clear(); return true; }
bool init(const dtNavMesh* nav) { m_ntiles = nav->getMaxTiles(); if (!m_ntiles) return true; m_tiles = (TileFlags*)dtAlloc(sizeof(TileFlags)*m_ntiles, DT_ALLOC_TEMP); if (!m_tiles) { return false; } memset(m_tiles, 0, sizeof(TileFlags)*m_ntiles); // Alloc flags for each tile. for (int i = 0; i < nav->getMaxTiles(); ++i) { const dtMeshTile* tile = nav->getTile(i); if (!tile->header) continue; TileFlags* tf = &m_tiles[i]; tf->nflags = tile->header->polyCount; tf->base = nav->getPolyRefBase(tile); if (tf->nflags) { tf->flags = (unsigned char*)dtAlloc(tf->nflags, DT_ALLOC_TEMP); if (!tf->flags) return false; memset(tf->flags, 0, tf->nflags); } } m_nav = nav; return false; }
void BotSaveOffMeshConnections( NavData_t *nav ) { char mapname[ MAX_QPATH ]; char filePath[ MAX_QPATH ]; fileHandle_t f = 0; Cvar_VariableStringBuffer( "mapname", mapname, sizeof( mapname ) ); Com_sprintf( filePath, sizeof( filePath ), "maps/%s-%s.navcon", mapname, nav->name ); f = FS_FOpenFileWrite( filePath ); if ( !f ) { return; } int conCount = nav->process.con.offMeshConCount; OffMeshConnectionHeader header; header.version = LittleLong( NAVMESHCON_VERSION ); header.numConnections = LittleLong( conCount ); FS_Write( &header, sizeof( header ), f ); size_t size = sizeof( float ) * 6 * conCount; float *verts = ( float * ) dtAlloc( size, DT_ALLOC_TEMP ); memcpy( verts, nav->process.con.verts, size ); SwapArray( verts, conCount * 6 ); FS_Write( verts, size, f ); dtFree( verts ); size = sizeof( float ) * conCount; float *rad = ( float * ) dtAlloc( size, DT_ALLOC_TEMP ); memcpy( rad, nav->process.con.rad, size ); SwapArray( rad, conCount ); FS_Write( rad, size, f ); dtFree( rad ); size = sizeof( unsigned short ) * conCount; unsigned short *flags = ( unsigned short * ) dtAlloc( size, DT_ALLOC_TEMP ); memcpy( flags, nav->process.con.flags, size ); SwapArray( flags, conCount ); FS_Write( flags, size, f ); dtFree( flags ); FS_Write( nav->process.con.areas, sizeof( unsigned char ) * conCount, f ); FS_Write( nav->process.con.dirs, sizeof( unsigned char ) * conCount, f ); size = sizeof( unsigned int ) * conCount; unsigned int *userids = ( unsigned int * ) dtAlloc( size, DT_ALLOC_TEMP ); memcpy( userids, nav->process.con.userids, size ); SwapArray( userids, conCount ); FS_Write( userids, size, f ); dtFree( userids ); FS_FCloseFile( f ); }
dtStatus dtTileCache::init(const dtTileCacheParams* params, dtTileCacheAlloc* talloc, dtTileCacheCompressor* tcomp, dtTileCacheMeshProcess* tmproc) { m_talloc = talloc; m_tcomp = tcomp; m_tmproc = tmproc; m_nreqs = 0; memcpy(&m_params, params, sizeof(m_params)); // Alloc space for obstacles. m_obstacles = (dtTileCacheObstacle*)dtAlloc(sizeof(dtTileCacheObstacle)*m_params.maxObstacles, DT_ALLOC_PERM); if (!m_obstacles) return DT_FAILURE | DT_OUT_OF_MEMORY; memset(m_obstacles, 0, sizeof(dtTileCacheObstacle)*m_params.maxObstacles); m_nextFreeObstacle = 0; for (int i = m_params.maxObstacles-1; i >= 0; --i) { m_obstacles[i].salt = 1; m_obstacles[i].next = m_nextFreeObstacle; m_nextFreeObstacle = &m_obstacles[i]; } // Init tiles m_tileLutSize = dtNextPow2(m_params.maxTiles/4); if (!m_tileLutSize) m_tileLutSize = 1; m_tileLutMask = m_tileLutSize-1; m_tiles = (dtCompressedTile*)dtAlloc(sizeof(dtCompressedTile)*m_params.maxTiles, DT_ALLOC_PERM); if (!m_tiles) return DT_FAILURE | DT_OUT_OF_MEMORY; m_posLookup = (dtCompressedTile**)dtAlloc(sizeof(dtCompressedTile*)*m_tileLutSize, DT_ALLOC_PERM); if (!m_posLookup) return DT_FAILURE | DT_OUT_OF_MEMORY; memset(m_tiles, 0, sizeof(dtCompressedTile)*m_params.maxTiles); memset(m_posLookup, 0, sizeof(dtCompressedTile*)*m_tileLutSize); m_nextFreeTile = 0; for (int i = m_params.maxTiles-1; i >= 0; --i) { m_tiles[i].salt = 1; m_tiles[i].next = m_nextFreeTile; m_nextFreeTile = &m_tiles[i]; } // Init ID generator values. m_tileBits = dtIlog2(dtNextPow2((unsigned int)m_params.maxTiles)); // Only allow 31 salt bits, since the salt mask is calculated using 32bit uint and it will overflow. m_saltBits = dtMin((unsigned int)31, 32 - m_tileBits); if (m_saltBits < 10) return DT_FAILURE | DT_INVALID_PARAM; return DT_SUCCESS; }
dtNodePool::dtNodePool(int maxNodes, int hashSize) : m_nodes(0), m_first(0), m_next(0), m_maxNodes(maxNodes), m_hashSize(hashSize), m_nodeCount(0) { m_nodes = (dtNode*)dtAlloc(sizeof(dtNode)*m_maxNodes, DT_ALLOC_PERM); m_next = (unsigned short*)dtAlloc(sizeof(unsigned short)*m_maxNodes, DT_ALLOC_PERM); m_first = (unsigned short*)dtAlloc(sizeof(unsigned short)*hashSize, DT_ALLOC_PERM); memset(m_first, 0xff, sizeof(unsigned short)*m_hashSize); memset(m_next, 0xff, sizeof(unsigned short)*m_maxNodes); }
dtNavMesh* dtAllocNavMesh() { void* mem = dtAlloc(sizeof(dtNavMesh), DT_ALLOC_PERM); if (!mem) return 0; return new(mem) dtNavMesh; }
dtNodeQueue::dtNodeQueue(int n) : m_heap(0), m_capacity(n), m_size(0) { m_heap = (dtNode**)dtAlloc(sizeof(dtNode*)*(m_capacity+1), DT_ALLOC_PERM); }
/// @par /// /// May be called more than once to purge and re-initialize the crowd. bool dtCrowd::init(const unsigned maxAgents, const float maxAgentRadius, dtNavMesh* nav) { purge(); m_disp = (float**) dtAlloc(sizeof(float*) * maxAgents, DT_ALLOC_PERM); for (unsigned i = 0; i < maxAgents; ++i) m_disp[i] = (float*) dtAlloc(sizeof(float) * 3, DT_ALLOC_PERM); // Creation of the crowd query void* mem = (dtCrowdQuery*) dtAlloc(sizeof(dtCrowdQuery), DT_ALLOC_PERM); if (!mem) return false; m_agentsEnv = (dtCrowdAgentEnvironment*) dtAlloc(sizeof(dtCrowdAgentEnvironment) * maxAgents, DT_ALLOC_PERM); if (!m_agentsEnv) return false; for (unsigned i = 0; i < maxAgents; ++i) new(&m_agentsEnv[i]) dtCrowdAgentEnvironment(); m_maxAgents = maxAgents; m_maxAgentRadius = maxAgentRadius; m_nbActiveAgents = 0; m_agentsToUpdate = (unsigned*) dtAlloc(sizeof(int) * maxAgents, DT_ALLOC_PERM); if (!m_agentsToUpdate) return false; for (unsigned i = 0; i < m_maxAgents; ++i) m_agentsToUpdate[i] = i; m_agents = (dtCrowdAgent*)dtAlloc(sizeof(dtCrowdAgent) * m_maxAgents, DT_ALLOC_PERM); if (!m_agents) return false; m_crowdQuery = new(mem) dtCrowdQuery(maxAgents, m_agents, m_agentsEnv); if (dtStatusFailed(m_crowdQuery->getNavMeshQuery()->init(nav, m_maxCommonNodes))) return false; m_activeAgents = (dtCrowdAgent**)dtAlloc(sizeof(dtCrowdAgent*) * m_maxAgents, DT_ALLOC_PERM); if (!m_activeAgents) return false; for (unsigned i = 0; i < m_maxAgents; ++i) { new(&m_agents[i]) dtCrowdAgent(); m_agents[i].active = 0; m_agents[i].id = i; m_agents[i].behavior = 0; m_agents[i].userData = 0; } m_crowdQuery->getQueryExtents()[0] = m_maxAgentRadius * 2.0f; m_crowdQuery->getQueryExtents()[1] = m_maxAgentRadius * 1.5f; m_crowdQuery->getQueryExtents()[2] = m_maxAgentRadius * 2.0f; return true; }
bool dtObstacleAvoidanceDebugData::init(const int maxSamples) { dtAssert(maxSamples); m_maxSamples = maxSamples; m_vel = (float*)dtAlloc(sizeof(float)*3*m_maxSamples, DT_ALLOC_PERM); if (!m_vel) return false; m_pen = (float*)dtAlloc(sizeof(float)*m_maxSamples, DT_ALLOC_PERM); if (!m_pen) return false; m_ssize = (float*)dtAlloc(sizeof(float)*m_maxSamples, DT_ALLOC_PERM); if (!m_ssize) return false; m_vpen = (float*)dtAlloc(sizeof(float)*m_maxSamples, DT_ALLOC_PERM); if (!m_vpen) return false; m_vcpen = (float*)dtAlloc(sizeof(float)*m_maxSamples, DT_ALLOC_PERM); if (!m_vcpen) return false; m_spen = (float*)dtAlloc(sizeof(float)*m_maxSamples, DT_ALLOC_PERM); if (!m_spen) return false; m_tpen = (float*)dtAlloc(sizeof(float)*m_maxSamples, DT_ALLOC_PERM); if (!m_tpen) return false; return true; }
bool dtObstacleAvoidanceQuery::init(const int maxCircles, const int maxSegments) { m_maxCircles = maxCircles; m_ncircles = 0; m_circles = (dtObstacleCircle*)dtAlloc(sizeof(dtObstacleCircle)*m_maxCircles, DT_ALLOC_PERM); if (!m_circles) return false; memset(m_circles, 0, sizeof(dtObstacleCircle)*m_maxCircles); m_maxSegments = maxSegments; m_nsegments = 0; m_segments = (dtObstacleSegment*)dtAlloc(sizeof(dtObstacleSegment)*m_maxSegments, DT_ALLOC_PERM); if (!m_segments) return false; memset(m_segments, 0, sizeof(dtObstacleSegment)*m_maxSegments); return true; }
dtCollisionAvoidance* dtCollisionAvoidance::allocate(unsigned nbMaxAgents) { void* mem = dtAlloc(sizeof(dtCollisionAvoidance), DT_ALLOC_PERM); if (mem) return new(mem) dtCollisionAvoidance(nbMaxAgents); return 0; }
dtStatus dtNavMesh::init(const dtNavMeshParams* params) { memcpy(&m_params, params, sizeof(dtNavMeshParams)); dtVcopy(m_orig, params->orig); m_tileWidth = params->tileWidth; m_tileHeight = params->tileHeight; // Init tiles m_maxTiles = params->maxTiles; m_tileLutSize = dtNextPow2(params->maxTiles/4); if (!m_tileLutSize) m_tileLutSize = 1; m_tileLutMask = m_tileLutSize-1; m_tiles = (dtMeshTile*)dtAlloc(sizeof(dtMeshTile)*m_maxTiles, DT_ALLOC_PERM); if (!m_tiles) return DT_FAILURE | DT_OUT_OF_MEMORY; m_posLookup = (dtMeshTile**)dtAlloc(sizeof(dtMeshTile*)*m_tileLutSize, DT_ALLOC_PERM); if (!m_posLookup) return DT_FAILURE | DT_OUT_OF_MEMORY; memset(m_tiles, 0, sizeof(dtMeshTile)*m_maxTiles); memset(m_posLookup, 0, sizeof(dtMeshTile*)*m_tileLutSize); m_nextFree = 0; for (int i = m_maxTiles-1; i >= 0; --i) { m_tiles[i].salt = 1; m_tiles[i].next = m_nextFree; m_nextFree = &m_tiles[i]; } /*// Init ID generator values. m_tileBits = dtIlog2(dtNextPow2((unsigned int)params->maxTiles)); m_polyBits = dtIlog2(dtNextPow2((unsigned int)params->maxPolys)); // Only allow 31 salt bits, since the salt mask is calculated using 32bit uint and it will overflow. m_saltBits = dtMin((unsigned int)31, 32 - m_tileBits - m_polyBits); if (m_saltBits < 10) return DT_FAILURE | DT_INVALID_PARAM;*/ // modified for CMaNGOS m_tileBits = STATIC_TILE_BITS; m_polyBits = STATIC_POLY_BITS; m_saltBits = STATIC_SALT_BITS; return DT_SUCCESS; }
/// @par /// /// @warning Cannot be called more than once. bool dtPathCorridor::init(const int maxPath) { dtAssert(!m_path); m_path = (dtPolyRef*)dtAlloc(sizeof(dtPolyRef)*maxPath, DT_ALLOC_PERM); if (!m_path) return false; m_npath = 0; m_maxPath = maxPath; return true; }
dtNavMesh* Sample_TileMesh::loadAll(const char* path) { FILE* fp = fopen(path, "rb"); if (!fp) return 0; // Read header. NavMeshSetHeader header; fread(&header, sizeof(NavMeshSetHeader), 1, fp); if (header.magic != NAVMESHSET_MAGIC) { fclose(fp); return 0; } if (header.version != NAVMESHSET_VERSION) { fclose(fp); return 0; } dtNavMesh* mesh = dtAllocNavMesh(); if (!mesh) { fclose(fp); return 0; } dtStatus status = mesh->init(&header.params); if (dtStatusFailed(status)) { fclose(fp); return 0; } // Read tiles. for (int i = 0; i < header.numTiles; ++i) { NavMeshTileHeader tileHeader; fread(&tileHeader, sizeof(tileHeader), 1, fp); if (!tileHeader.tileRef || !tileHeader.dataSize) break; unsigned char* data = (unsigned char*)dtAlloc(tileHeader.dataSize, DT_ALLOC_PERM); if (!data) break; memset(data, 0, tileHeader.dataSize); fread(data, tileHeader.dataSize, 1, fp); mesh->addTile(data, tileHeader.dataSize, DT_TILE_FREE_DATA, tileHeader.tileRef, 0); } fclose(fp); return mesh; }
dtNodePool::dtNodePool(int maxNodes, int hashSize) : m_nodes(0), m_first(0), m_next(0), m_maxNodes(maxNodes), m_hashSize(hashSize), m_nodeCount(0) { dtAssert(dtNextPow2(m_hashSize) == (unsigned int)m_hashSize); dtAssert(m_maxNodes > 0); m_nodes = (dtNode*)dtAlloc(sizeof(dtNode)*m_maxNodes, DT_ALLOC_PERM); m_next = (dtNodeRef*)dtAlloc(sizeof(dtNodeRef)*m_maxNodes, DT_ALLOC_PERM); m_first = (dtNodeRef*)dtAlloc(sizeof(dtNodeRef)*hashSize, DT_ALLOC_PERM); dtAssert(m_nodes); dtAssert(m_next); dtAssert(m_first); memset(m_first, 0xff, sizeof(dtNodeRef)*m_hashSize); memset(m_next, 0xff, sizeof(dtNodeRef)*m_maxNodes); }
void resize(int n) { if (n > m_cap) { if (!m_cap) m_cap = n; while (m_cap < n) m_cap *= 2; dtPolyRef* newData = (dtPolyRef*)dtAlloc(m_cap*sizeof(dtPolyRef), DT_ALLOC_TEMP); if (m_size && newData) memcpy(newData, m_data, m_size*sizeof(dtPolyRef)); dtFree(m_data); m_data = newData; } m_size = n; }
dtStatus dtNavMesh::init(const dtNavMeshParams* params) { memcpy(&m_params, params, sizeof(dtNavMeshParams)); dtVcopy(m_orig, params->orig); m_tileWidth = params->tileWidth; m_tileHeight = params->tileHeight; // Init tiles m_maxTiles = params->maxTiles; m_tileLutSize = dtNextPow2(params->maxTiles/4); if (!m_tileLutSize) m_tileLutSize = 1; m_tileLutMask = m_tileLutSize-1; m_tiles = (dtMeshTile*)dtAlloc(sizeof(dtMeshTile)*m_maxTiles, DT_ALLOC_PERM); if (!m_tiles) return DT_FAILURE | DT_OUT_OF_MEMORY; m_posLookup = (dtMeshTile**)dtAlloc(sizeof(dtMeshTile*)*m_tileLutSize, DT_ALLOC_PERM); if (!m_posLookup) return DT_FAILURE | DT_OUT_OF_MEMORY; memset(m_tiles, 0, sizeof(dtMeshTile)*m_maxTiles); memset(m_posLookup, 0, sizeof(dtMeshTile*)*m_tileLutSize); m_nextFree = 0; for (int i = m_maxTiles-1; i >= 0; --i) { m_tiles[i].salt = 1; m_tiles[i].next = m_nextFree; m_nextFree = &m_tiles[i]; } // Init ID generator values. m_tileBits = STATIC_TILE_BITS; //dtIlog2(dtNextPow2((unsigned int)params->maxTiles)); m_polyBits = STATIC_POLY_BITS; //dtIlog2(dtNextPow2((unsigned int)params->maxPolys)); m_saltBits = STATIC_SALT_BITS; //sizeof(dtPolyRef)*8 - m_tileBits - m_polyBits; //if (m_saltBits < SALT_MIN_BITS) //return DT_FAILURE | DT_INVALID_PARAM; return DT_SUCCESS; }
bool dtNavMesh::init(const dtNavMeshParams* params) { memcpy(&m_params, params, sizeof(dtNavMeshParams)); dtVcopy(m_orig, params->orig); m_tileWidth = params->tileWidth; m_tileHeight = params->tileHeight; // Init tiles m_maxTiles = params->maxTiles; m_tileLutSize = dtNextPow2(params->maxTiles/4); if (!m_tileLutSize) m_tileLutSize = 1; m_tileLutMask = m_tileLutSize-1; m_tiles = (dtMeshTile*)dtAlloc(sizeof(dtMeshTile)*m_maxTiles, DT_ALLOC_PERM); if (!m_tiles) return false; m_posLookup = (dtMeshTile**)dtAlloc(sizeof(dtMeshTile*)*m_tileLutSize, DT_ALLOC_PERM); if (!m_posLookup) return false; memset(m_tiles, 0, sizeof(dtMeshTile)*m_maxTiles); memset(m_posLookup, 0, sizeof(dtMeshTile*)*m_tileLutSize); m_nextFree = 0; for (int i = m_maxTiles-1; i >= 0; --i) { m_tiles[i].salt = 1; m_tiles[i].next = m_nextFree; m_nextFree = &m_tiles[i]; } // Init ID generator values. m_tileBits = dtMax((unsigned int)1, dtIlog2(dtNextPow2((unsigned int)params->maxTiles))); m_polyBits = dtMax((unsigned int)1, dtIlog2(dtNextPow2((unsigned int)params->maxPolys))); m_saltBits = 32 - m_tileBits - m_polyBits; if (m_saltBits < 10) return false; return true; }
void CCollideInterface::LoadNavMeshTile(uint32 mapId, uint32 tileX, uint32 tileY) { NavMeshData* nav = GetNavMesh(mapId); if(nav == NULL) return; char filename[1024]; sprintf(filename, "mmaps/%03i%02i%02i.mmtile", mapId, tileX, tileY); FILE* f = fopen(filename, "rb"); if(f == NULL) { //printf("Failed to load: %s\n", filename); return; } MmapTileHeader header; fread(&header, sizeof(MmapTileHeader), 1, f); if(header.mmapMagic != MMAP_MAGIC || header.mmapVersion != MMAP_VERSION) { sLog.Debug("NavMesh", "Load failed (%u %u %u): tile headers incorrect", mapId, tileX, tileY); //printf("Load failed (%u %u %u): tile headers incorrect\n", mapId, tileX, tileY); fclose(f); return; } uint8* data = (uint8*)dtAlloc(header.size, DT_ALLOC_PERM); if(data == NULL) { //printf("Load failed (%u %u %u): data incorrect\n", mapId, tileX, tileY); fclose(f); return; } fread(data, 1, header.size, f); fclose(f); dtTileRef dtref; nav->mesh->addTile(data, header.size, DT_TILE_FREE_DATA, 0, &dtref); nav->tilelock.Acquire(); nav->tilerefs.insert(std::make_pair(tileX | (tileY << 16), dtref)); nav->tilelock.Release(); }
bool dtCollisionAvoidance::init(unsigned maxCircles, unsigned maxSegments) { purge(); m_maxCircles = maxCircles; m_ncircles = 0; m_circles = (dtObstacleCircle*)dtAlloc(sizeof(dtObstacleCircle)*m_maxCircles, DT_ALLOC_PERM); if (!m_circles) return false; memset(m_circles, 0, sizeof(dtObstacleCircle)*m_maxCircles); m_maxSegments = maxSegments; m_nsegments = 0; m_segments = (dtObstacleSegment*)dtAlloc(sizeof(dtObstacleSegment)*m_maxSegments, DT_ALLOC_PERM); if (!m_segments) return false; memset(m_segments, 0, sizeof(dtObstacleSegment)*m_maxSegments); return true; }
dtStatus dtNavMesh::init(const dtNavMeshParams* params) { memcpy(&m_params, params, sizeof(dtNavMeshParams)); dtVcopy(m_orig, params->orig); m_tileWidth = params->tileWidth; m_tileHeight = params->tileHeight; // Init tiles m_maxTiles = params->maxTiles; m_tileLutSize = dtNextPow2(params->maxTiles/4); if (!m_tileLutSize) m_tileLutSize = 1; m_tileLutMask = m_tileLutSize-1; m_tiles = (dtMeshTile*)dtAlloc(sizeof(dtMeshTile)*m_maxTiles, DT_ALLOC_PERM); if (!m_tiles) return DT_FAILURE | DT_OUT_OF_MEMORY; m_posLookup = (dtMeshTile**)dtAlloc(sizeof(dtMeshTile*)*m_tileLutSize, DT_ALLOC_PERM); if (!m_posLookup) return DT_FAILURE | DT_OUT_OF_MEMORY; memset(m_tiles, 0, sizeof(dtMeshTile)*m_maxTiles); memset(m_posLookup, 0, sizeof(dtMeshTile*)*m_tileLutSize); m_nextFree = 0; for (int i = m_maxTiles-1; i >= 0; --i) { m_tiles[i].salt = 1; m_tiles[i].next = m_nextFree; m_nextFree = &m_tiles[i]; } // Edited by OC m_tileBits = STATIC_TILE_BITS; m_polyBits = STATIC_POLY_BITS; m_saltBits = STATIC_SALT_BITS; return DT_SUCCESS; }
static int createBVTree(const unsigned short* verts, const int /*nverts*/, const unsigned short* polys, const int npolys, const int nvp, const float cs, const float ch, const int /*nnodes*/, dtBVNode* nodes) { // Build tree BVItem* items = (BVItem*)dtAlloc(sizeof(BVItem)*npolys, DT_ALLOC_TEMP); for (int i = 0; i < npolys; i++) { BVItem& it = items[i]; it.i = i; // Calc polygon bounds. const unsigned short* p = &polys[i*nvp*2]; it.bmin[0] = it.bmax[0] = verts[p[0]*3+0]; it.bmin[1] = it.bmax[1] = verts[p[0]*3+1]; it.bmin[2] = it.bmax[2] = verts[p[0]*3+2]; for (int j = 1; j < nvp; ++j) { if (p[j] == MESH_NULL_IDX) break; unsigned short x = verts[p[j]*3+0]; unsigned short y = verts[p[j]*3+1]; unsigned short z = verts[p[j]*3+2]; if (x < it.bmin[0]) it.bmin[0] = x; if (y < it.bmin[1]) it.bmin[1] = y; if (z < it.bmin[2]) it.bmin[2] = z; if (x > it.bmax[0]) it.bmax[0] = x; if (y > it.bmax[1]) it.bmax[1] = y; if (z > it.bmax[2]) it.bmax[2] = z; } // Remap y it.bmin[1] = (unsigned short)floorf((float)it.bmin[1]*ch/cs); it.bmax[1] = (unsigned short)ceilf((float)it.bmax[1]*ch/cs); } int curNode = 0; subdivide(items, npolys, 0, npolys, curNode, nodes); dtFree(items); return curNode; }
EXPORT_API bool dtnmBuildTileDataRaw(unsigned char* data , int dataSize , rcnTileData* resultData) { if (!data || !resultData || resultData->data) // Already has data in it. Not allowed. { return false; } resultData->data = (unsigned char*)dtAlloc( sizeof(unsigned char)*dataSize, DT_ALLOC_PERM); if (!resultData->data) return false; memcpy(resultData->data, data, dataSize); resultData->dataSize = dataSize; resultData->isOwned = false; return true; }
bool dtPathQueue::init(const int maxPathSize, const int maxSearchNodeCount, dtNavMesh* nav) { purge(); m_navquery = dtAllocNavMeshQuery(); if (!m_navquery) return false; if (dtStatusFailed(m_navquery->init(nav, maxSearchNodeCount))) return false; m_maxPathSize = maxPathSize; for (int i = 0; i < MAX_QUEUE; ++i) { m_queue[i].ref = DT_PATHQ_INVALID; m_queue[i].path = (dtPolyRef*)dtAlloc(sizeof(dtPolyRef)*m_maxPathSize, DT_ALLOC_PERM); if (!m_queue[i].path) return false; } m_queueHead = 0; return true; }
dtObstacleAvoidanceDebugData* dtAllocObstacleAvoidanceDebugData() { void* mem = dtAlloc(sizeof(dtObstacleAvoidanceDebugData), DT_ALLOC_PERM); if (!mem) return 0; return new(mem) dtObstacleAvoidanceDebugData; }
dtObstacleAvoidanceQuery* dtAllocObstacleAvoidanceQuery() { void* mem = dtAlloc(sizeof(dtObstacleAvoidanceQuery), DT_ALLOC_PERM); if (!mem) return 0; return new(mem) dtObstacleAvoidanceQuery; }
bool OgreDetourTileCache::loadAll(Ogre::String filename) { FILE* fp = fopen(filename.data(), "rb"); if (!fp) { Ogre::LogManager::getSingletonPtr()->logMessage("Error: OgreDetourTileCache::loadAll("+filename+"). Could not open file."); return false; } // Read header. TileCacheSetHeader header; fread(&header, sizeof(TileCacheSetHeader), 1, fp); if (header.magic != TILECACHESET_MAGIC) { fclose(fp); Ogre::LogManager::getSingletonPtr()->logMessage("Error: OgreDetourTileCache::loadAll("+filename+"). File does not appear to contain valid tilecache data."); return false; } if (header.version != TILECACHESET_VERSION) { fclose(fp); Ogre::LogManager::getSingletonPtr()->logMessage("Error: OgreDetourTileCache::loadAll("+filename+"). File contains a different version of the tilecache data format ("+Ogre::StringConverter::toString(header.version)+" instead of "+Ogre::StringConverter::toString(TILECACHESET_VERSION)+")."); return false; } m_recast->m_navMesh = dtAllocNavMesh(); if (!m_recast->m_navMesh) { fclose(fp); Ogre::LogManager::getSingletonPtr()->logMessage("Error: OgreDetourTileCache::loadAll("+filename+"). Could not allocate navmesh."); return false; } dtStatus status = m_recast->m_navMesh->init(&header.meshParams); if (dtStatusFailed(status)) { fclose(fp); Ogre::LogManager::getSingletonPtr()->logMessage("Error: OgreDetourTileCache::loadAll("+filename+"). Could not init navmesh."); return false; } m_tileCache = dtAllocTileCache(); if (!m_tileCache) { fclose(fp); Ogre::LogManager::getSingletonPtr()->logMessage("Error: OgreDetourTileCache::loadAll("+filename+"). Could not allocate tilecache."); return false; } status = m_tileCache->init(&header.cacheParams, m_talloc, m_tcomp, m_tmproc); if (dtStatusFailed(status)) { fclose(fp); Ogre::LogManager::getSingletonPtr()->logMessage("Error: OgreDetourTileCache::loadAll("+filename+"). Could not init tilecache."); return false; } memcpy(&m_cfg, &header.recastConfig, sizeof(rcConfig)); // Read tiles. for (int i = 0; i < header.numTiles; ++i) { TileCacheTileHeader tileHeader; fread(&tileHeader, sizeof(tileHeader), 1, fp); if (!tileHeader.tileRef || !tileHeader.dataSize) break; unsigned char* data = (unsigned char*)dtAlloc(tileHeader.dataSize, DT_ALLOC_PERM); if (!data) break; memset(data, 0, tileHeader.dataSize); fread(data, tileHeader.dataSize, 1, fp); dtCompressedTileRef tile = 0; m_tileCache->addTile(data, tileHeader.dataSize, DT_COMPRESSEDTILE_FREE_DATA, &tile); if (tile) m_tileCache->buildNavMeshTile(tile, m_recast->m_navMesh); } fclose(fp); // Init recast navmeshquery with created navmesh (in OgreRecast component) m_recast->m_navQuery = dtAllocNavMeshQuery(); m_recast->m_navQuery->init(m_recast->m_navMesh, 2048); // Config // TODO handle this nicer, also inputGeom is not inited, making some functions crash m_cellSize = m_cfg.cs; m_tileSize = m_cfg.tileSize; // cache bounding box const float* bmin = m_cfg.bmin; const float* bmax = m_cfg.bmax; // Copy loaded config back to recast module memcpy(&m_recast->m_cfg, &m_cfg, sizeof(rcConfig)); m_tileSize = m_cfg.tileSize; m_cellSize = m_cfg.cs; m_tcparams = header.cacheParams; // Determine grid size (number of tiles) based on bounding box and grid cell size int gw = 0, gh = 0; rcCalcGridSize(bmin, bmax, m_cellSize, &gw, &gh); // Calculates total size of voxel grid const int ts = m_tileSize; const int tw = (gw + ts-1) / ts; // Tile width const int th = (gh + ts-1) / ts; // Tile height m_tw = tw; m_th = th; Ogre::LogManager::getSingletonPtr()->logMessage("Total Voxels: "+Ogre::StringConverter::toString(gw) + " x " + Ogre::StringConverter::toString(gh)); Ogre::LogManager::getSingletonPtr()->logMessage("Tilesize: "+Ogre::StringConverter::toString(m_tileSize)+" Cellsize: "+Ogre::StringConverter::toString(m_cellSize)); Ogre::LogManager::getSingletonPtr()->logMessage("Tiles: "+Ogre::StringConverter::toString(m_tw)+" x "+Ogre::StringConverter::toString(m_th)); // Max tiles and max polys affect how the tile IDs are caculated. // There are 22 bits available for identifying a tile and a polygon. int tileBits = rcMin((int)dtIlog2(dtNextPow2(tw*th*EXPECTED_LAYERS_PER_TILE)), 14); if (tileBits > 14) tileBits = 14; int polyBits = 22 - tileBits; m_maxTiles = 1 << tileBits; m_maxPolysPerTile = 1 << polyBits; Ogre::LogManager::getSingletonPtr()->logMessage("Max Tiles: " + Ogre::StringConverter::toString(m_maxTiles)); Ogre::LogManager::getSingletonPtr()->logMessage("Max Polys: " + Ogre::StringConverter::toString(m_maxPolysPerTile)); // End config //// buildInitialNavmesh(); return true; }
bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, int* outDataSize) { if (params->nvp > DT_VERTS_PER_POLYGON) return false; if (params->vertCount >= 0xffff) return false; if (!params->vertCount || !params->verts) return false; if (!params->polyCount || !params->polys) return false; if (!params->detailMeshes || !params->detailVerts || !params->detailTris) return false; const int nvp = params->nvp; // Classify off-mesh connection points. We store only the connections // whose start point is inside the tile. unsigned char* offMeshConClass = 0; int storedOffMeshConCount = 0; int offMeshConLinkCount = 0; if (params->offMeshConCount > 0) { offMeshConClass = (unsigned char*)dtAlloc(sizeof(unsigned char)*params->offMeshConCount*2, DT_ALLOC_TEMP); if (!offMeshConClass) return false; for (int i = 0; i < params->offMeshConCount; ++i) { offMeshConClass[i*2+0] = classifyOffMeshPoint(¶ms->offMeshConVerts[(i*2+0)*3], params->bmin, params->bmax); offMeshConClass[i*2+1] = classifyOffMeshPoint(¶ms->offMeshConVerts[(i*2+1)*3], params->bmin, params->bmax); // Cound how many links should be allocated for off-mesh connections. if (offMeshConClass[i*2+0] == 0xff) offMeshConLinkCount++; if (offMeshConClass[i*2+1] == 0xff) offMeshConLinkCount++; if (offMeshConClass[i*2+0] == 0xff) storedOffMeshConCount++; } } // Off-mesh connectionss are stored as polygons, adjust values. const int totPolyCount = params->polyCount + storedOffMeshConCount; const int totVertCount = params->vertCount + storedOffMeshConCount*2; // Find portal edges which are at tile borders. int edgeCount = 0; int portalCount = 0; for (int i = 0; i < params->polyCount; ++i) { const unsigned short* p = ¶ms->polys[i*2*nvp]; for (int j = 0; j < nvp; ++j) { if (p[j] == MESH_NULL_IDX) break; int nj = j+1; if (nj >= nvp || p[nj] == MESH_NULL_IDX) nj = 0; const unsigned short* va = ¶ms->verts[p[j]*3]; const unsigned short* vb = ¶ms->verts[p[nj]*3]; edgeCount++; if (params->tileSize > 0) { if (va[0] == params->tileSize && vb[0] == params->tileSize) portalCount++; // x+ else if (va[2] == params->tileSize && vb[2] == params->tileSize) portalCount++; // z+ else if (va[0] == 0 && vb[0] == 0) portalCount++; // x- else if (va[2] == 0 && vb[2] == 0) portalCount++; // z- } } } const int maxLinkCount = edgeCount + portalCount*2 + offMeshConLinkCount*2; // Find unique detail vertices. int uniqueDetailVertCount = 0; for (int i = 0; i < params->polyCount; ++i) { const unsigned short* p = ¶ms->polys[i*nvp*2]; int ndv = params->detailMeshes[i*4+1]; int nv = 0; for (int j = 0; j < nvp; ++j) { if (p[j] == MESH_NULL_IDX) break; nv++; } ndv -= nv; uniqueDetailVertCount += ndv; } // Calculate data size const int headerSize = dtAlign4(sizeof(dtMeshHeader)); const int vertsSize = dtAlign4(sizeof(float)*3*totVertCount); const int polysSize = dtAlign4(sizeof(dtPoly)*totPolyCount); const int linksSize = dtAlign4(sizeof(dtLink)*maxLinkCount); const int detailMeshesSize = dtAlign4(sizeof(dtPolyDetail)*params->polyCount); const int detailVertsSize = dtAlign4(sizeof(float)*3*uniqueDetailVertCount); const int detailTrisSize = dtAlign4(sizeof(unsigned char)*4*params->detailTriCount); const int bvTreeSize = dtAlign4(sizeof(dtBVNode)*params->polyCount*2); const int offMeshConsSize = dtAlign4(sizeof(dtOffMeshConnection)*storedOffMeshConCount); const int dataSize = headerSize + vertsSize + polysSize + linksSize + detailMeshesSize + detailVertsSize + detailTrisSize + bvTreeSize + offMeshConsSize; unsigned char* data = (unsigned char*)dtAlloc(sizeof(unsigned char)*dataSize, DT_ALLOC_PERM); if (!data) { dtFree(offMeshConClass); return false; } memset(data, 0, dataSize); unsigned char* d = data; dtMeshHeader* header = (dtMeshHeader*)d; d += headerSize; float* navVerts = (float*)d; d += vertsSize; dtPoly* navPolys = (dtPoly*)d; d += polysSize; d += linksSize; dtPolyDetail* navDMeshes = (dtPolyDetail*)d; d += detailMeshesSize; float* navDVerts = (float*)d; d += detailVertsSize; unsigned char* navDTris = (unsigned char*)d; d += detailTrisSize; dtBVNode* navBvtree = (dtBVNode*)d; d += bvTreeSize; dtOffMeshConnection* offMeshCons = (dtOffMeshConnection*)d; d += offMeshConsSize; // Store header header->magic = DT_NAVMESH_MAGIC; header->version = DT_NAVMESH_VERSION; header->x = params->tileX; header->y = params->tileY; header->userId = params->userId; header->polyCount = totPolyCount; header->vertCount = totVertCount; header->maxLinkCount = maxLinkCount; dtVcopy(header->bmin, params->bmin); dtVcopy(header->bmax, params->bmax); header->detailMeshCount = params->polyCount; header->detailVertCount = uniqueDetailVertCount; header->detailTriCount = params->detailTriCount; header->bvQuantFactor = 1.0f / params->cs; header->offMeshBase = params->polyCount; header->walkableHeight = params->walkableHeight; header->walkableRadius = params->walkableRadius; header->walkableClimb = params->walkableClimb; header->offMeshConCount = storedOffMeshConCount; header->bvNodeCount = params->polyCount*2; const int offMeshVertsBase = params->vertCount; const int offMeshPolyBase = params->polyCount; // Store vertices // Mesh vertices for (int i = 0; i < params->vertCount; ++i) { const unsigned short* iv = ¶ms->verts[i*3]; float* v = &navVerts[i*3]; v[0] = params->bmin[0] + iv[0] * params->cs; v[1] = params->bmin[1] + iv[1] * params->ch; v[2] = params->bmin[2] + iv[2] * params->cs; } // Off-mesh link vertices. int n = 0; for (int i = 0; i < params->offMeshConCount; ++i) { // Only store connections which start from this tile. if (offMeshConClass[i*2+0] == 0xff) { const float* linkv = ¶ms->offMeshConVerts[i*2*3]; float* v = &navVerts[(offMeshVertsBase + n*2)*3]; dtVcopy(&v[0], &linkv[0]); dtVcopy(&v[3], &linkv[3]); n++; } } // Store polygons // Mesh polys const unsigned short* src = params->polys; for (int i = 0; i < params->polyCount; ++i) { dtPoly* p = &navPolys[i]; p->vertCount = 0; p->flags = params->polyFlags[i]; p->area = params->polyAreas[i]; p->type = DT_POLYTYPE_GROUND; for (int j = 0; j < nvp; ++j) { if (src[j] == MESH_NULL_IDX) break; p->verts[j] = src[j]; p->neis[j] = (src[nvp+j]+1) & 0xffff; p->vertCount++; } src += nvp*2; } // Off-mesh connection vertices. n = 0; for (int i = 0; i < params->offMeshConCount; ++i) { // Only store connections which start from this tile. if (offMeshConClass[i*2+0] == 0xff) { dtPoly* p = &navPolys[offMeshPolyBase+n]; p->vertCount = 2; p->verts[0] = (unsigned short)(offMeshVertsBase + n*2+0); p->verts[1] = (unsigned short)(offMeshVertsBase + n*2+1); p->flags = params->offMeshConFlags[i]; p->area = params->offMeshConAreas[i]; p->type = DT_POLYTYPE_OFFMESH_CONNECTION; n++; } } // Store portal edges. if (params->tileSize > 0) { for (int i = 0; i < params->polyCount; ++i) { dtPoly* poly = &navPolys[i]; for (int j = 0; j < poly->vertCount; ++j) { int nj = j+1; if (nj >= poly->vertCount) nj = 0; const unsigned short* va = ¶ms->verts[poly->verts[j]*3]; const unsigned short* vb = ¶ms->verts[poly->verts[nj]*3]; if (va[0] == params->tileSize && vb[0] == params->tileSize) // x+ poly->neis[j] = DT_EXT_LINK | 0; else if (va[2] == params->tileSize && vb[2] == params->tileSize) // z+ poly->neis[j] = DT_EXT_LINK | 2; else if (va[0] == 0 && vb[0] == 0) // x- poly->neis[j] = DT_EXT_LINK | 4; else if (va[2] == 0 && vb[2] == 0) // z- poly->neis[j] = DT_EXT_LINK | 6; } } } // Store detail meshes and vertices. // The nav polygon vertices are stored as the first vertices on each mesh. // We compress the mesh data by skipping them and using the navmesh coordinates. unsigned short vbase = 0; for (int i = 0; i < params->polyCount; ++i) { dtPolyDetail& dtl = navDMeshes[i]; const int vb = params->detailMeshes[i*4+0]; const int ndv = params->detailMeshes[i*4+1]; const int nv = navPolys[i].vertCount; dtl.vertBase = vbase; dtl.vertCount = (unsigned short)(ndv-nv); dtl.triBase = params->detailMeshes[i*4+2]; dtl.triCount = params->detailMeshes[i*4+3]; // Copy vertices except the first 'nv' verts which are equal to nav poly verts. if (ndv-nv) { memcpy(&navDVerts[vbase*3], ¶ms->detailVerts[(vb+nv)*3], sizeof(float)*3*(ndv-nv)); vbase += (unsigned short)(ndv-nv); } } // Store triangles. memcpy(navDTris, params->detailTris, sizeof(unsigned char)*4*params->detailTriCount); // Store and create BVtree. // TODO: take detail mesh into account! use byte per bbox extent? createBVTree(params->verts, params->vertCount, params->polys, params->polyCount, nvp, params->cs, params->ch, params->polyCount*2, navBvtree); // Store Off-Mesh connections. n = 0; for (int i = 0; i < params->offMeshConCount; ++i) { // Only store connections which start from this tile. if (offMeshConClass[i*2+0] == 0xff) { dtOffMeshConnection* con = &offMeshCons[n]; con->poly = (unsigned short)(offMeshPolyBase + n); // Copy connection end-points. const float* endPts = ¶ms->offMeshConVerts[i*2*3]; dtVcopy(&con->pos[0], &endPts[0]); dtVcopy(&con->pos[3], &endPts[3]); con->rad = params->offMeshConRad[i]; con->flags = params->offMeshConDir[i] ? DT_OFFMESH_CON_BIDIR : 0; con->side = offMeshConClass[i*2+1]; n++; } } dtFree(offMeshConClass); *outData = data; *outDataSize = dataSize; return true; }
bool CNavMesh::load(char* path) { this->path = path; this->unload(); m_navMesh = new dtNavMesh(); FILE* fp = fopen(path, "rb"); if (!fp) { ShowError("CNavMesh::load Error loading navmesh (%s)\n", path); return false; } // Read header. NavMeshSetHeader header; fread(&header, sizeof(NavMeshSetHeader), 1, fp); if (header.magic != NAVMESHSET_MAGIC) { fclose(fp); return false; } if (header.version != NAVMESHSET_VERSION) { fclose(fp); return false; } m_navMesh = dtAllocNavMesh(); if (!m_navMesh) { fclose(fp); return false; } dtStatus status = m_navMesh->init(&header.params); if (dtStatusFailed(status)) { ShowError("CNavMesh::load Could not initialize detour for (%s)", path); outputError(status); fclose(fp); return false; } // Read tiles. for (int i = 0; i < header.numTiles; ++i) { NavMeshTileHeader tileHeader; fread(&tileHeader, sizeof(tileHeader), 1, fp); if (!tileHeader.tileRef || !tileHeader.dataSize) break; unsigned char* data = (unsigned char*)dtAlloc(tileHeader.dataSize, DT_ALLOC_PERM); if (!data) break; memset(data, 0, tileHeader.dataSize); fread(data, tileHeader.dataSize, 1, fp); m_navMesh->addTile(data, tileHeader.dataSize, DT_TILE_FREE_DATA, tileHeader.tileRef, 0); } fclose(fp); m_navMeshQuery = new dtNavMeshQuery(); // init detour nav mesh path finder status = m_navMeshQuery->init(m_navMesh, MAX_NAV_POLYS); if(dtStatusFailed(status)) { ShowError("CNavMesh::load Error loading navmeshquery (%s)\n", path); outputError(status); return false; } return true; }
void resize(const size_t cap) { if (buffer) dtFree(buffer); buffer = (unsigned char*)dtAlloc(cap, DT_ALLOC_PERM); capacity = cap; }