Update Vmaps | Mmaps | Recastnav and fixed FleeingMovement

- Fixes getHeight collision (Map height is now calculated properly core-side, extraction of Maps, Vmaps is required)

- Fixes invisible walls causing LoS errores and wrong pathing in some zones.

- Mmaps update, padding is used, now to ensure proper binary-identical mmtiles

- Updated Recastnav to work properly with new updates

- Updated Area Storage

- Implement Map out of Bound (players will pop on closest graveyard if out of bounds)

- FleeingMovementGenerator updated, LoS calc to not go out of bounds or in/under textured when 
fleeing

- Added command .mmap, port from TC (info about mmaps)
This commit is contained in:
sucofog
2017-11-14 15:14:43 +01:00
committed by Yehonal
parent d98ba9cdaa
commit e772b08c68
79 changed files with 5037 additions and 3018 deletions

View File

@@ -12,8 +12,10 @@
file(GLOB_RECURSE sources *.cpp *.h)
set(include_Dirs
${CMAKE_SOURCE_DIR}/modules/worldengine/nucleus/src/Utilities
${CMAKE_SOURCE_DIR}/modules/worldengine/nucleus/src
${CMAKE_SOURCE_DIR}/modules/worldengine/deps/libmpq
${CMAKE_SOURCE_DIR}/modules/worldengine/deps/g3dlite/include
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/loadlib
)

View File

@@ -20,9 +20,12 @@
#include "dbcfile.h"
#include "mpq_libmpq04.h"
#include "StringFormat.h"
#include "adt.h"
#include "wdt.h"
#include "G3D/Plane.h"
#include <fcntl.h>
#if defined( __GNUC__ )
@@ -49,11 +52,10 @@ typedef struct
} map_id;
map_id *map_ids;
uint16 *areas;
uint16 *LiqType;
char output_path[128] = ".";
char input_path[128] = ".";
uint32 maxAreaId = 0;
#define MAX_PATH_LENGTH 128
char output_path[MAX_PATH_LENGTH] = ".";
char input_path[MAX_PATH_LENGTH] = ".";
// **************************************************
// Extractor options
@@ -244,30 +246,6 @@ uint32 ReadMapDBC()
return map_count;
}
void ReadAreaTableDBC()
{
printf("Read AreaTable.dbc file...");
DBCFile dbc("DBFilesClient\\AreaTable.dbc");
if(!dbc.open())
{
printf("Fatal error: Invalid AreaTable.dbc file format!\n");
exit(1);
}
size_t area_count = dbc.getRecordCount();
size_t maxid = dbc.getMaxId();
areas = new uint16[maxid + 1];
memset(areas, 0xff, (maxid + 1) * sizeof(uint16));
for(uint32 x = 0; x < area_count; ++x)
areas[dbc.getRecord(x).getUInt(0)] = dbc.getRecord(x).getUInt(3);
maxAreaId = dbc.getMaxId();
printf("Done! (%u areas loaded)\n", (uint32)area_count);
}
void ReadLiquidTypeTableDBC()
{
printf("Read LiquidType.dbc file...");
@@ -295,7 +273,7 @@ void ReadLiquidTypeTableDBC()
// Map file format data
static char const* MAP_MAGIC = "MAPS";
static char const* MAP_VERSION_MAGIC = "v1.3";
static char const* MAP_VERSION_MAGIC = "v1.8";
static char const* MAP_AREA_MAGIC = "AREA";
static char const* MAP_HEIGHT_MAGIC = "MHGT";
static char const* MAP_LIQUID_MAGIC = "MLIQ";
@@ -324,9 +302,10 @@ struct map_areaHeader
uint16 gridArea;
};
#define MAP_HEIGHT_NO_HEIGHT 0x0001
#define MAP_HEIGHT_AS_INT16 0x0002
#define MAP_HEIGHT_AS_INT8 0x0004
#define MAP_HEIGHT_NO_HEIGHT 0x0001
#define MAP_HEIGHT_AS_INT16 0x0002
#define MAP_HEIGHT_AS_INT8 0x0004
#define MAP_HEIGHT_HAS_FLIGHT_BOUNDS 0x0008
struct map_heightHeader
{
@@ -371,7 +350,7 @@ float selectUInt16StepStore(float maxDiff)
return 65535 / maxDiff;
}
// Temporary grid data store
uint16 area_flags[ADT_CELLS_PER_GRID][ADT_CELLS_PER_GRID];
uint16 area_ids[ADT_CELLS_PER_GRID][ADT_CELLS_PER_GRID];
float V8[ADT_GRID_SIZE][ADT_GRID_SIZE];
float V9[ADT_GRID_SIZE+1][ADT_GRID_SIZE+1];
@@ -385,17 +364,20 @@ uint8 liquid_flags[ADT_CELLS_PER_GRID][ADT_CELLS_PER_GRID];
bool liquid_show[ADT_GRID_SIZE][ADT_GRID_SIZE];
float liquid_height[ADT_GRID_SIZE+1][ADT_GRID_SIZE+1];
bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/, uint32 build)
int16 flight_box_max[3][3];
int16 flight_box_min[3][3];
bool ConvertADT(std::string const& inputPath, std::string const& outputPath, int /*cell_y*/, int /*cell_x*/, uint32 build)
{
ADT_file adt;
if (!adt.loadFile(filename))
if (!adt.loadFile(inputPath))
return false;
adt_MCIN *cells = adt.a_grid->getMCIN();
if (!cells)
{
printf("Can't find cells in '%s'\n", filename);
printf("Can't find cells in '%s'\n", inputPath.c_str());
return false;
}
@@ -405,39 +387,25 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/,
// Prepare map header
map_fileheader map;
map.mapMagic = *(uint32 const*)MAP_MAGIC;
map.versionMagic = *(uint32 const*)MAP_VERSION_MAGIC;
map.mapMagic = *reinterpret_cast<uint32 const*>(MAP_MAGIC);
map.versionMagic = *reinterpret_cast<uint32 const*>(MAP_VERSION_MAGIC);
map.buildMagic = build;
// Get area flags data
for (int i=0;i<ADT_CELLS_PER_GRID;i++)
{
for(int j=0;j<ADT_CELLS_PER_GRID;j++)
{
adt_MCNK * cell = cells->getMCNK(i,j);
uint32 areaid = cell->areaid;
if(areaid && areaid <= maxAreaId)
{
if(areas[areaid] != 0xffff)
{
area_flags[i][j] = areas[areaid];
continue;
}
printf("File: %s\nCan't find area flag for areaid %u [%d, %d].\n", filename, areaid, cell->ix, cell->iy);
}
area_flags[i][j] = 0xffff;
}
}
for (int i = 0; i < ADT_CELLS_PER_GRID; i++)
for (int j = 0; j < ADT_CELLS_PER_GRID; j++)
area_ids[i][j] = cells->getMCNK(i, j)->areaid;
//============================================
// Try pack area data
//============================================
bool fullAreaData = false;
uint32 areaflag = area_flags[0][0];
for (int y=0;y<ADT_CELLS_PER_GRID;y++)
uint32 areaId = area_ids[0][0];
for (int y = 0; y < ADT_CELLS_PER_GRID; ++y)
{
for(int x=0;x<ADT_CELLS_PER_GRID;x++)
for (int x = 0; x < ADT_CELLS_PER_GRID; ++x)
{
if(area_flags[y][x]!=areaflag)
if (area_ids[y][x] != areaId)
{
fullAreaData = true;
break;
@@ -449,27 +417,27 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/,
map.areaMapSize = sizeof(map_areaHeader);
map_areaHeader areaHeader;
areaHeader.fourcc = *(uint32 const*)MAP_AREA_MAGIC;
areaHeader.fourcc = *reinterpret_cast<uint32 const*>(MAP_AREA_MAGIC);
areaHeader.flags = 0;
if (fullAreaData)
{
areaHeader.gridArea = 0;
map.areaMapSize+=sizeof(area_flags);
map.areaMapSize += sizeof(area_ids);
}
else
{
areaHeader.flags |= MAP_AREA_NO_AREA;
areaHeader.gridArea = (uint16)areaflag;
areaHeader.gridArea = static_cast<uint16>(areaId);
}
//
// Get Height map from grid
//
for (int i=0;i<ADT_CELLS_PER_GRID;i++)
for (int i = 0; i<ADT_CELLS_PER_GRID; i++)
{
for(int j=0;j<ADT_CELLS_PER_GRID;j++)
for (int j = 0; j<ADT_CELLS_PER_GRID; j++)
{
adt_MCNK * cell = cells->getMCNK(i,j);
adt_MCNK * cell = cells->getMCNK(i, j);
if (!cell)
continue;
// Height values for triangles stored in order:
@@ -489,22 +457,22 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/,
// . . . . . . . .
// Set map height as grid height
for (int y=0; y <= ADT_CELL_SIZE; y++)
for (int y = 0; y <= ADT_CELL_SIZE; y++)
{
int cy = i*ADT_CELL_SIZE + y;
for (int x=0; x <= ADT_CELL_SIZE; x++)
for (int x = 0; x <= ADT_CELL_SIZE; x++)
{
int cx = j*ADT_CELL_SIZE + x;
V9[cy][cx]=cell->ypos;
V9[cy][cx] = cell->ypos;
}
}
for (int y=0; y < ADT_CELL_SIZE; y++)
for (int y = 0; y < ADT_CELL_SIZE; y++)
{
int cy = i*ADT_CELL_SIZE + y;
for (int x=0; x < ADT_CELL_SIZE; x++)
for (int x = 0; x < ADT_CELL_SIZE; x++)
{
int cx = j*ADT_CELL_SIZE + x;
V8[cy][cx]=cell->ypos;
V8[cy][cx] = cell->ypos;
}
}
// Get custom height
@@ -512,23 +480,23 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/,
if (!v)
continue;
// get V9 height map
for (int y=0; y <= ADT_CELL_SIZE; y++)
for (int y = 0; y <= ADT_CELL_SIZE; y++)
{
int cy = i*ADT_CELL_SIZE + y;
for (int x=0; x <= ADT_CELL_SIZE; x++)
for (int x = 0; x <= ADT_CELL_SIZE; x++)
{
int cx = j*ADT_CELL_SIZE + x;
V9[cy][cx]+=v->height_map[y*(ADT_CELL_SIZE*2+1)+x];
V9[cy][cx] += v->height_map[y*(ADT_CELL_SIZE * 2 + 1) + x];
}
}
// get V8 height map
for (int y=0; y < ADT_CELL_SIZE; y++)
for (int y = 0; y < ADT_CELL_SIZE; y++)
{
int cy = i*ADT_CELL_SIZE + y;
for (int x=0; x < ADT_CELL_SIZE; x++)
for (int x = 0; x < ADT_CELL_SIZE; x++)
{
int cx = j*ADT_CELL_SIZE + x;
V8[cy][cx]+=v->height_map[y*(ADT_CELL_SIZE*2+1)+ADT_CELL_SIZE+1+x];
V8[cy][cx] += v->height_map[y*(ADT_CELL_SIZE * 2 + 1) + ADT_CELL_SIZE + 1 + x];
}
}
}
@@ -538,18 +506,18 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/,
//============================================
float maxHeight = -20000;
float minHeight = 20000;
for (int y=0; y<ADT_GRID_SIZE; y++)
for (int y = 0; y<ADT_GRID_SIZE; y++)
{
for(int x=0;x<ADT_GRID_SIZE;x++)
for (int x = 0; x<ADT_GRID_SIZE; x++)
{
float h = V8[y][x];
if (maxHeight < h) maxHeight = h;
if (minHeight > h) minHeight = h;
}
}
for (int y=0; y<=ADT_GRID_SIZE; y++)
for (int y = 0; y <= ADT_GRID_SIZE; y++)
{
for(int x=0;x<=ADT_GRID_SIZE;x++)
for(int x = 0; x<= ADT_GRID_SIZE; x++)
{
float h = V9[y][x];
if (maxHeight < h) maxHeight = h;
@@ -560,12 +528,12 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/,
// Check for allow limit minimum height (not store height in deep ochean - allow save some memory)
if (CONF_allow_height_limit && minHeight < CONF_use_minHeight)
{
for (int y=0; y<ADT_GRID_SIZE; y++)
for(int x=0;x<ADT_GRID_SIZE;x++)
for (int y = 0; y<ADT_GRID_SIZE; y++)
for (int x = 0; x<ADT_GRID_SIZE; x++)
if (V8[y][x] < CONF_use_minHeight)
V8[y][x] = CONF_use_minHeight;
for (int y=0; y<=ADT_GRID_SIZE; y++)
for(int x=0;x<=ADT_GRID_SIZE;x++)
for (int y = 0; y <= ADT_GRID_SIZE; y++)
for (int x = 0; x <= ADT_GRID_SIZE; x++)
if (V9[y][x] < CONF_use_minHeight)
V9[y][x] = CONF_use_minHeight;
if (minHeight < CONF_use_minHeight)
@@ -574,11 +542,19 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/,
maxHeight = CONF_use_minHeight;
}
bool hasFlightBox = false;
if (adt_MFBO* mfbo = adt.a_grid->getMFBO())
{
memcpy(flight_box_max, &mfbo->max, sizeof(flight_box_max));
memcpy(flight_box_min, &mfbo->min, sizeof(flight_box_min));
hasFlightBox = true;
}
map.heightMapOffset = map.areaMapOffset + map.areaMapSize;
map.heightMapSize = sizeof(map_heightHeader);
map_heightHeader heightHeader;
heightHeader.fourcc = *(uint32 const*)MAP_HEIGHT_MAGIC;
heightHeader.fourcc = *reinterpret_cast<uint32 const*>(MAP_HEIGHT_MAGIC);
heightHeader.flags = 0;
heightHeader.gridHeight = minHeight;
heightHeader.gridMaxHeight = maxHeight;
@@ -589,6 +565,12 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/,
// Not need store if flat surface
if (CONF_allow_float_to_int && (maxHeight - minHeight) < CONF_flat_height_delta_limit)
heightHeader.flags |= MAP_HEIGHT_NO_HEIGHT;
if (hasFlightBox)
{
heightHeader.flags |= MAP_HEIGHT_HAS_FLIGHT_BOUNDS;
map.heightMapSize += sizeof(flight_box_max) + sizeof(flight_box_min);
}
// Try store as packed in uint16 or uint8 values
if (!(heightHeader.flags & MAP_HEIGHT_NO_HEIGHT))
@@ -600,12 +582,12 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/,
float diff = maxHeight - minHeight;
if (diff < CONF_float_to_int8_limit) // As uint8 (max accuracy = CONF_float_to_int8_limit/256)
{
heightHeader.flags|=MAP_HEIGHT_AS_INT8;
heightHeader.flags |= MAP_HEIGHT_AS_INT8;
step = selectUInt8StepStore(diff);
}
else if (diff<CONF_float_to_int16_limit) // As uint16 (max accuracy = CONF_float_to_int16_limit/65536)
{
heightHeader.flags|=MAP_HEIGHT_AS_INT16;
heightHeader.flags |= MAP_HEIGHT_AS_INT16;
step = selectUInt16StepStore(diff);
}
}
@@ -613,32 +595,32 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/,
// Pack it to int values if need
if (heightHeader.flags&MAP_HEIGHT_AS_INT8)
{
for (int y=0; y<ADT_GRID_SIZE; y++)
for(int x=0;x<ADT_GRID_SIZE;x++)
for (int y = 0; y<ADT_GRID_SIZE; y++)
for (int x = 0; x<ADT_GRID_SIZE; x++)
uint8_V8[y][x] = uint8((V8[y][x] - minHeight) * step + 0.5f);
for (int y=0; y<=ADT_GRID_SIZE; y++)
for(int x=0;x<=ADT_GRID_SIZE;x++)
for (int y = 0; y <= ADT_GRID_SIZE; y++)
for (int x = 0; x <= ADT_GRID_SIZE; x++)
uint8_V9[y][x] = uint8((V9[y][x] - minHeight) * step + 0.5f);
map.heightMapSize+= sizeof(uint8_V9) + sizeof(uint8_V8);
map.heightMapSize += sizeof(uint8_V9) + sizeof(uint8_V8);
}
else if (heightHeader.flags&MAP_HEIGHT_AS_INT16)
{
for (int y=0; y<ADT_GRID_SIZE; y++)
for(int x=0;x<ADT_GRID_SIZE;x++)
for (int y = 0; y<ADT_GRID_SIZE; y++)
for (int x = 0; x<ADT_GRID_SIZE; x++)
uint16_V8[y][x] = uint16((V8[y][x] - minHeight) * step + 0.5f);
for (int y=0; y<=ADT_GRID_SIZE; y++)
for(int x=0;x<=ADT_GRID_SIZE;x++)
for (int y = 0; y <= ADT_GRID_SIZE; y++)
for (int x = 0; x <= ADT_GRID_SIZE; x++)
uint16_V9[y][x] = uint16((V9[y][x] - minHeight) * step + 0.5f);
map.heightMapSize+= sizeof(uint16_V9) + sizeof(uint16_V8);
map.heightMapSize += sizeof(uint16_V9) + sizeof(uint16_V8);
}
else
map.heightMapSize+= sizeof(V9) + sizeof(V8);
map.heightMapSize += sizeof(V9) + sizeof(V8);
}
// Get from MCLQ chunk (old)
for (int i = 0; i < ADT_CELLS_PER_GRID; i++)
{
for(int j = 0; j < ADT_CELLS_PER_GRID; j++)
for (int j = 0; j < ADT_CELLS_PER_GRID; j++)
{
adt_MCNK *cell = cells->getMCNK(i, j);
if (!cell)
@@ -658,7 +640,7 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/,
if (liquid->flags[y][x] != 0x0F)
{
liquid_show[cy][cx] = true;
if (liquid->flags[y][x] & (1<<7))
if (liquid->flags[y][x] & (1 << 7))
liquid_flags[i][j] |= MAP_LIQUID_TYPE_DARK_WATER;
++count;
}
@@ -666,17 +648,17 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/,
}
uint32 c_flag = cell->flags;
if (c_flag & (1<<2))
if (c_flag & (1 << 2))
{
liquid_entry[i][j] = 1;
liquid_flags[i][j] |= MAP_LIQUID_TYPE_WATER; // water
}
if (c_flag & (1<<3))
if (c_flag & (1 << 3))
{
liquid_entry[i][j] = 2;
liquid_flags[i][j] |= MAP_LIQUID_TYPE_OCEAN; // ocean
}
if (c_flag & (1<<4))
if (c_flag & (1 << 4))
{
liquid_entry[i][j] = 3;
liquid_flags[i][j] |= MAP_LIQUID_TYPE_MAGMA; // magma/slime
@@ -734,7 +716,7 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/,
case LIQUID_TYPE_MAGMA: liquid_flags[i][j] |= MAP_LIQUID_TYPE_MAGMA; break;
case LIQUID_TYPE_SLIME: liquid_flags[i][j] |= MAP_LIQUID_TYPE_SLIME; break;
default:
printf("\nCan't find Liquid type %u for map %s\nchunk %d,%d\n", h->liquidType, filename, i, j);
printf("\nCan't find Liquid type %u for map %s\nchunk %d,%d\n", h->liquidType, inputPath.c_str(), i, j);
break;
}
// Dark water detect
@@ -877,17 +859,17 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/,
map.holesSize = 0;
// Ok all data prepared - store it
FILE* output = fopen(filename2, "wb");
FILE* output = fopen(outputPath.c_str(), "wb");
if (!output)
{
printf("Can't create the output file '%s'\n", filename2);
printf("Can't create the output file '%s'\n", outputPath.c_str());
return false;
}
fwrite(&map, sizeof(map), 1, output);
// Store area data
fwrite(&areaHeader, sizeof(areaHeader), 1, output);
if (!(areaHeader.flags&MAP_AREA_NO_AREA))
fwrite(area_flags, sizeof(area_flags), 1, output);
fwrite(area_ids, sizeof(area_ids), 1, output);
// Store height data
fwrite(&heightHeader, sizeof(heightHeader), 1, output);
@@ -910,6 +892,12 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/,
}
}
if (heightHeader.flags & MAP_HEIGHT_HAS_FLIGHT_BOUNDS)
{
fwrite(flight_box_max, sizeof(flight_box_max), 1, output);
fwrite(flight_box_min, sizeof(flight_box_min), 1, output);
}
// Store liquid data if need
if (map.liquidMapOffset)
{
@@ -937,15 +925,14 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/,
void ExtractMapsFromMpq(uint32 build)
{
char mpq_filename[1024];
char output_filename[1024];
char mpq_map_name[1024];
std::string mpqFileName;
std::string outputFileName;
std::string mpqMapName;
printf("Extracting maps...\n");
uint32 map_count = ReadMapDBC();
ReadAreaTableDBC();
ReadLiquidTypeTableDBC();
std::string path = output_path;
@@ -957,9 +944,9 @@ void ExtractMapsFromMpq(uint32 build)
{
printf("Extract %s (%d/%u) \n", map_ids[z].name, z+1, map_count);
// Loadup map grid data
sprintf(mpq_map_name, "World\\Maps\\%s\\%s.wdt", map_ids[z].name, map_ids[z].name);
mpqMapName = Trinity::StringFormat("World\\Maps\\%s\\%s.wdt", map_ids[z].name, map_ids[z].name);
WDT_file wdt;
if (!wdt.loadFile(mpq_map_name, false))
if (!wdt.loadFile(mpqMapName, false))
{
// printf("Error loading %s map wdt data\n", map_ids[z].name);
continue;
@@ -971,17 +958,16 @@ void ExtractMapsFromMpq(uint32 build)
{
if (!wdt.main->adt_list[y][x].exist)
continue;
sprintf(mpq_filename, "World\\Maps\\%s\\%s_%u_%u.adt", map_ids[z].name, map_ids[z].name, x, y);
sprintf(output_filename, "%s/maps/%03u%02u%02u.map", output_path, map_ids[z].id, y, x);
ConvertADT(mpq_filename, output_filename, y, x, build);
mpqFileName = Trinity::StringFormat("World\\Maps\\%s\\%s_%u_%u.adt", map_ids[z].name, map_ids[z].name, x, y);
outputFileName = Trinity::StringFormat("%s/maps/%03u%02u%02u.map", output_path, map_ids[z].id, y, x);
ConvertADT(mpqFileName, outputFileName, y, x, build);
}
// draw progress bar
printf("Processing........................%d%%\r", (100 * (y+1)) / WDT_MAP_SIZE);
}
}
printf("\n");
delete [] areas;
delete [] map_ids;
delete[] map_ids;
}
bool ExtractFile( char const* mpq_name, std::string const& filename )

View File

@@ -9,15 +9,16 @@
#include "adt.h"
// Helper
int holetab_h[4] = {0x1111, 0x2222, 0x4444, 0x8888};
int holetab_v[4] = {0x000F, 0x00F0, 0x0F00, 0xF000};
int holetab_h[4] = { 0x1111, 0x2222, 0x4444, 0x8888 };
int holetab_v[4] = { 0x000F, 0x00F0, 0x0F00, 0xF000 };
u_map_fcc MHDRMagic = { {'R','D','H','M'} };
u_map_fcc MCINMagic = { {'N','I','C','M'} };
u_map_fcc MH2OMagic = { {'O','2','H','M'} };
u_map_fcc MCNKMagic = { {'K','N','C','M'} };
u_map_fcc MCVTMagic = { {'T','V','C','M'} };
u_map_fcc MCLQMagic = { {'Q','L','C','M'} };
u_map_fcc MHDRMagic = { { 'R','D','H','M' } };
u_map_fcc MCINMagic = { { 'N','I','C','M' } };
u_map_fcc MH2OMagic = { { 'O','2','H','M' } };
u_map_fcc MCNKMagic = { { 'K','N','C','M' } };
u_map_fcc MCVTMagic = { { 'T','V','C','M' } };
u_map_fcc MCLQMagic = { { 'Q','L','C','M' } };
u_map_fcc MFBOMagic = { { 'O','B','F','M' } };
bool isHole(int holes, int i, int j)
{
@@ -69,7 +70,7 @@ bool adt_MHDR::prepareLoadedData()
if (fcc != MHDRMagic.fcc)
return false;
if (size!=sizeof(adt_MHDR)-8)
if (size != sizeof(adt_MHDR) - 8)
return false;
// Check and prepare MCIN
@@ -80,6 +81,9 @@ bool adt_MHDR::prepareLoadedData()
if (offsMH2O && !getMH2O()->prepareLoadedData())
return false;
if (offsMFBO && flags & 1 && !getMFBO()->prepareLoadedData())
return false;
return true;
}
@@ -142,3 +146,8 @@ bool adt_MCLQ::prepareLoadedData()
return true;
}
bool adt_MFBO::prepareLoadedData()
{
return fcc == MFBOMagic.fcc;
}

View File

@@ -248,6 +248,27 @@ public:
};
// Adt file min/max height chunk
//
class adt_MFBO
{
union
{
uint32 fcc;
char fcc_txt[4];
};
public:
uint32 size;
struct plane
{
int16 coords[9];
};
plane max;
plane min;
bool prepareLoadedData();
};
//
// Adt file header chunk
//
@@ -260,12 +281,12 @@ class adt_MHDR
public:
uint32 size;
uint32 pad;
uint32 flags;
uint32 offsMCIN; // MCIN
uint32 offsTex; // MTEX
uint32 offsModels; // MMDX
uint32 offsModelsIds; // MMID
uint32 offsMapObejcts; // MWMO
uint32 offsTex; // MTEX
uint32 offsModels; // MMDX
uint32 offsModelsIds; // MMID
uint32 offsMapObejcts; // MWMO
uint32 offsMapObejctsIds; // MWID
uint32 offsDoodsDef; // MDDF
uint32 offsObjectsDef; // MODF
@@ -278,9 +299,22 @@ public:
uint32 data5;
public:
bool prepareLoadedData();
adt_MCIN *getMCIN(){ return (adt_MCIN *)((uint8 *)&pad+offsMCIN);}
adt_MH2O *getMH2O(){ return offsMH2O ? (adt_MH2O *)((uint8 *)&pad+offsMH2O) : 0;}
adt_MCIN* getMCIN()
{
return reinterpret_cast<adt_MCIN*>(reinterpret_cast<uint8*>(&flags) + offsMCIN);
}
adt_MH2O* getMH2O()
{
if (offsMH2O)
return reinterpret_cast<adt_MH2O*>(reinterpret_cast<uint8*>(&flags) + offsMH2O);
return nullptr;
}
adt_MFBO* getMFBO()
{
if (flags & 1 && offsMFBO)
return reinterpret_cast<adt_MFBO*>(reinterpret_cast<uint8*>(&flags) + offsMFBO);
return nullptr;
}
};
class ADT_file : public FileLoader{

View File

@@ -26,14 +26,14 @@ FileLoader::~FileLoader()
free();
}
bool FileLoader::loadFile(char *filename, bool log)
bool FileLoader::loadFile(std::string const& fileName, bool log)
{
free();
MPQFile mf(filename);
MPQFile mf(fileName.c_str());
if(mf.isEof())
{
if (log)
printf("No such file %s\n", filename);
printf("No such file %s\n", fileName.c_str());
return false;
}
@@ -45,7 +45,7 @@ bool FileLoader::loadFile(char *filename, bool log)
if (prepareLoadedData())
return true;
printf("Error loading %s", filename);
printf("Error loading %s", fileName.c_str());
mf.close();
free();
return false;

View File

@@ -7,6 +7,8 @@
#ifndef LOAD_LIB_H
#define LOAD_LIB_H
#include <string>
#ifdef _WIN32
typedef __int64 int64;
typedef __int32 int32;
@@ -65,7 +67,7 @@ public:
file_MVER *version;
FileLoader();
~FileLoader();
bool loadFile(char *filename, bool log = true);
bool loadFile(std::string const& filename, bool log = true);
virtual void free();
};
#endif

View File

@@ -341,7 +341,7 @@ public:
};
#define MMAP_MAGIC 0x4d4d4150 // 'MMAP'
#define MMAP_VERSION 3
#define MMAP_VERSION 6
struct MmapTileHeader
{

View File

@@ -24,7 +24,7 @@ namespace DisableMgr
}
#define MMAP_MAGIC 0x4d4d4150 // 'MMAP'
#define MMAP_VERSION 3
#define MMAP_VERSION 6
struct MmapTileHeader
{
@@ -32,12 +32,22 @@ struct MmapTileHeader
uint32 dtVersion;
uint32 mmapVersion;
uint32 size;
bool usesLiquids : 1;
char usesLiquids;
char padding[3];
MmapTileHeader() : mmapMagic(MMAP_MAGIC), dtVersion(DT_NAVMESH_VERSION),
mmapVersion(MMAP_VERSION), size(0), usesLiquids(true) {}
mmapVersion(MMAP_VERSION), size(0), usesLiquids(true), padding() {}
};
// All padding fields must be handled and initialized to ensure mmaps_generator will produce binary-identical *.mmtile files
static_assert(sizeof(MmapTileHeader) == 20, "MmapTileHeader size is not correct, adjust the padding field size");
static_assert(sizeof(MmapTileHeader) == (sizeof(MmapTileHeader::mmapMagic) +
sizeof(MmapTileHeader::dtVersion) +
sizeof(MmapTileHeader::mmapVersion) +
sizeof(MmapTileHeader::size) +
sizeof(MmapTileHeader::usesLiquids) +
sizeof(MmapTileHeader::padding)), "MmapTileHeader has uninitialized padding fields");
namespace MMAP
{
MapBuilder::MapBuilder(float maxWalkableAngle, bool skipLiquid,
@@ -57,6 +67,10 @@ namespace MMAP
m_rcContext = new rcContext(false);
// percentageDone - Initializing
m_totalTiles = 0;
m_totalTilesBuilt = 0;
discoverTiles();
}
@@ -65,8 +79,8 @@ namespace MMAP
{
for (TileList::iterator it = m_tiles.begin(); it != m_tiles.end(); ++it)
{
(*it).second->clear();
delete (*it).second;
(*it).m_tiles->clear();
delete (*it).m_tiles;
}
delete m_terrainBuilder;
@@ -85,9 +99,9 @@ namespace MMAP
for (uint32 i = 0; i < files.size(); ++i)
{
mapID = uint32(atoi(files[i].substr(0,3).c_str()));
if (m_tiles.find(mapID) == m_tiles.end())
if (std::find(m_tiles.begin(), m_tiles.end(), mapID) == m_tiles.end())
{
m_tiles.insert(std::pair<uint32, std::set<uint32>*>(mapID, new std::set<uint32>));
m_tiles.emplace_back(MapTiles(mapID, new std::set<uint32>));
count++;
}
}
@@ -97,8 +111,11 @@ namespace MMAP
for (uint32 i = 0; i < files.size(); ++i)
{
mapID = uint32(atoi(files[i].substr(0,3).c_str()));
m_tiles.insert(std::pair<uint32, std::set<uint32>*>(mapID, new std::set<uint32>));
count++;
if (std::find(m_tiles.begin(), m_tiles.end(), mapID) == m_tiles.end())
{
m_tiles.emplace_back(MapTiles(mapID, new std::set<uint32>));
count++;
}
}
printf("found %u.\n", count);
@@ -106,8 +123,8 @@ namespace MMAP
printf("Discovering tiles... ");
for (TileList::iterator itr = m_tiles.begin(); itr != m_tiles.end(); ++itr)
{
std::set<uint32>* tiles = (*itr).second;
mapID = (*itr).first;
std::set<uint32>* tiles = (*itr).m_tiles;
mapID = (*itr).m_mapId;
sprintf(filter, "%03u*.vmtile", mapID);
files.clear();
@@ -136,17 +153,20 @@ namespace MMAP
}
}
printf("found %u.\n\n", count);
// percentageDone - total tiles to process
m_totalTiles = count;
}
/**************************************************************************/
std::set<uint32>* MapBuilder::getTileList(uint32 mapID)
{
TileList::iterator itr = m_tiles.find(mapID);
TileList::iterator itr = std::find(m_tiles.begin(), m_tiles.end(), mapID);
if (itr != m_tiles.end())
return (*itr).second;
return (*itr).m_tiles;
std::set<uint32>* tiles = new std::set<uint32>();
m_tiles.insert(std::pair<uint32, std::set<uint32>*>(mapID, tiles));
m_tiles.emplace_back(MapTiles(mapID, tiles));
return tiles;
}
@@ -157,9 +177,14 @@ namespace MMAP
BuilderThreadPool* pool = threads > 0 ? new BuilderThreadPool() : NULL;
m_tiles.sort([](MapTiles a, MapTiles b)
{
return a.m_tiles->size() > b.m_tiles->size();
});
for (TileList::iterator it = m_tiles.begin(); it != m_tiles.end(); ++it)
{
uint32 mapID = it->first;
uint32 mapID = it->m_mapId;
if (!shouldSkipMap(mapID))
{
if (threads > 0)
@@ -382,7 +407,8 @@ namespace MMAP
/**************************************************************************/
void MapBuilder::buildTile(uint32 mapID, uint32 tileX, uint32 tileY, dtNavMesh* navMesh)
{
printf("[Map %03i] Building tile [%02u,%02u]\n", mapID, tileX, tileY);
// percentageDone - added, now it will show addional reference percentage done of the overall process
printf("%u%% [Map %03i] Building tile [%02u,%02u]\n", percentageDone(m_totalTiles, m_totalTilesBuilt), mapID, tileX, tileY);
MeshData meshData;
@@ -416,6 +442,9 @@ namespace MMAP
// build navmesh tile
buildMoveMapTile(mapID, tileX, tileY, meshData, bmin, bmax, navMesh);
// percentageDone - increment tiles built
m_totalTilesBuilt++;
}
/**************************************************************************/
@@ -970,5 +999,13 @@ namespace MMAP
return true;
}
/**************************************************************************/
uint32 MapBuilder::percentageDone(uint32 totalTiles, uint32 totalTilesBuilt)
{
if (totalTiles)
return totalTilesBuilt * 100 / totalTiles;
return 0;
}
}

View File

@@ -9,7 +9,9 @@
#include <vector>
#include <set>
#include <atomic>
#include <map>
#include <list>
#include "TerrainBuilder.h"
#include "IntermediateValues.h"
@@ -27,7 +29,24 @@ using namespace VMAP;
namespace MMAP
{
typedef std::map<uint32, std::set<uint32>*> TileList;
struct MapTiles
{
MapTiles() : m_mapId(uint32(-1)), m_tiles(NULL) {}
MapTiles(uint32 id, std::set<uint32>* tiles) : m_mapId(id), m_tiles(tiles) {}
~MapTiles() {}
uint32 m_mapId;
std::set<uint32>* m_tiles;
bool operator==(uint32 id)
{
return m_mapId == id;
}
};
typedef std::list<MapTiles> TileList;
struct Tile
{
Tile() : chf(NULL), solid(NULL), cset(NULL), pmesh(NULL), dmesh(NULL) {}
@@ -96,6 +115,8 @@ namespace MMAP
bool shouldSkipMap(uint32 mapID);
bool isTransportMap(uint32 mapID);
bool shouldSkipTile(uint32 mapID, uint32 tileX, uint32 tileY);
// percentageDone - method to calculate percentage
uint32 percentageDone(uint32 totalTiles, uint32 totalTilesDone);
TerrainBuilder* m_terrainBuilder;
TileList m_tiles;
@@ -109,6 +130,9 @@ namespace MMAP
float m_maxWalkableAngle;
bool m_bigBaseUnit;
// percentageDone - variables to calculate percentage
uint32 m_totalTiles;
std::atomic<uint32> m_totalTilesBuilt;
// build performance - not really used for now
rcContext* m_rcContext;

View File

@@ -9,9 +9,8 @@
#include <string>
#include <vector>
#include <ace/OS_NS_sys_time.h>
#include "Define.h"
#include "Common.h"
#ifndef _WIN32
#include <stddef.h>
@@ -125,26 +124,6 @@ namespace MMAP
return LISTFILE_OK;
}
inline uint32 getMSTime()
{
static const ACE_Time_Value ApplicationStartTime = ACE_OS::gettimeofday();
return (ACE_OS::gettimeofday() - ApplicationStartTime).msec();
}
inline uint32 getMSTimeDiff(uint32 oldMSTime, uint32 newMSTime)
{
// getMSTime() have limited data range and this is case when it overflow in this tick
if (oldMSTime > newMSTime)
return (0xFFFFFFFF - oldMSTime) + newMSTime;
else
return newMSTime - oldMSTime;
}
inline uint32 GetMSTimeDiffToNow(uint32 oldMSTime)
{
return getMSTimeDiff(oldMSTime, getMSTime());
}
}
#endif

View File

@@ -6,6 +6,7 @@
#include "PathCommon.h"
#include "MapBuilder.h"
#include "Timer.h"
using namespace MMAP;

View File

@@ -70,7 +70,7 @@ struct map_liquidHeader
namespace MMAP
{
char const* MAP_VERSION_MAGIC = "v1.3";
char const* MAP_VERSION_MAGIC = "v1.8";
TerrainBuilder::TerrainBuilder(bool skipLiquid) : m_skipLiquid (skipLiquid){ }
TerrainBuilder::~TerrainBuilder() { }

View File

@@ -7,6 +7,8 @@
#ifndef LOAD_LIB_H
#define LOAD_LIB_H
#include <string>
#ifdef WIN32
typedef __int64 int64;
typedef __int32 int32;
@@ -59,7 +61,7 @@ public:
file_MVER *version;
FileLoader();
~FileLoader();
bool loadFile(char *filename, bool log = true);
bool loadFile(std::string const& filename, bool log = true);
virtual void free();
};
#endif

View File

@@ -84,17 +84,31 @@ bool Model::ConvertToVMAPModel(const char * outfilename)
wsize = sizeof(uint32) + sizeof(unsigned short) * nIndexes;
fwrite(&wsize, sizeof(int), 1, output);
fwrite(&nIndexes, sizeof(uint32), 1, output);
if (nIndexes >0)
if (nIndexes > 0)
{
for (uint32 i = 0; i < nIndexes; ++i)
{
if ((i % 3) - 1 == 0 && i + 1 < nIndexes)
{
uint16 tmp = indices[i];
indices[i] = indices[i + 1];
indices[i + 1] = tmp;
}
}
fwrite(indices, sizeof(unsigned short), nIndexes, output);
}
fwrite("VERT", 4, 1, output);
wsize = sizeof(int) + sizeof(float) * 3 * nVertices;
fwrite(&wsize, sizeof(int), 1, output);
fwrite(&nVertices, sizeof(int), 1, output);
if (nVertices >0)
{
for(uint32 vpos=0; vpos <nVertices; ++vpos)
std::swap(vertices[vpos].y, vertices[vpos].z);
for (uint32 vpos = 0; vpos < nVertices; ++vpos)
{
float tmp = vertices[vpos].y;
vertices[vpos].y = -vertices[vpos].z;
vertices[vpos].z = tmp;
}
fwrite(vertices, sizeof(float)*3, nVertices, output);
}
@@ -169,7 +183,6 @@ ModelInstance::ModelInstance(MPQFile& f, char const* ModelInstName, uint32 mapID
int realy1 = (int) ((float) pos.z / 533.333333f);
int realx2 = (int) ((float) pos.x / 533.333333f);
int realy2 = (int) ((float) pos.z / 533.333333f);
fprintf(pDirfile,"%s/%s %f,%f,%f_%f,%f,%f %f %d %d %d,%d %d\n",
MapName,
ModelInstName,

View File

@@ -20,6 +20,10 @@ if(CMAKE_SYSTEM_NAME MATCHES "Linux")
if(SERVERS AND NOT NOJEM)
add_subdirectory(jemalloc)
endif()
if(TOOLS)
add_subdirectory(bzip2)
endif()
add_subdirectory(zlib)
endif()
if(CMAKE_SYSTEM_NAME MATCHES "Windows")

View File

@@ -1,4 +1,4 @@
# Copyright (C)
# Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
#
# This file is free software; as a special exception the author gives
# unlimited permission to copy and/or distribute it, with or without
@@ -9,20 +9,25 @@
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
set(Detour_STAT_SRCS
DetourAlloc.cpp
DetourCommon.cpp
DetourNavMesh.cpp
DetourNavMeshBuilder.cpp
DetourNavMeshQuery.cpp
DetourNode.cpp
Source/DetourAlloc.cpp
Source/DetourCommon.cpp
Source/DetourNavMesh.cpp
Source/DetourNavMeshBuilder.cpp
Source/DetourNavMeshQuery.cpp
Source/DetourNode.cpp
)
if(WIN32)
include_directories(
${CMAKE_SOURCE_DIR}/modules/worldengine/deps/zlib
)
endif()
add_library(Detour STATIC ${Detour_STAT_SRCS})
target_link_libraries(Detour ${ZLIB_LIBRARIES})
target_include_directories(Detour
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/Include)
target_link_libraries(Detour
PUBLIC
zlib)
set_target_properties(Detour
PROPERTIES
FOLDER
"dep")

View File

@@ -1,36 +0,0 @@
//
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#ifndef DETOURALLOCATOR_H
#define DETOURALLOCATOR_H
enum dtAllocHint
{
DT_ALLOC_PERM, // Memory persist after a function call.
DT_ALLOC_TEMP // Memory used temporarily within a function.
};
typedef void* (dtAllocFunc)(int size, dtAllocHint hint);
typedef void (dtFreeFunc)(void* ptr);
void dtAllocSetCustom(dtAllocFunc *allocFunc, dtFreeFunc *freeFunc);
void* dtAlloc(int size, dtAllocHint hint);
void dtFree(void* ptr);
#endif

View File

@@ -1,248 +0,0 @@
//
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#ifndef DETOURCOMMON_H
#define DETOURCOMMON_H
template<class T> inline void dtSwap(T& a, T& b) { T t = a; a = b; b = t; }
template<class T> inline T dtMin(T a, T b) { return a < b ? a : b; }
template<class T> inline T dtMax(T a, T b) { return a > b ? a : b; }
template<class T> inline T dtAbs(T a) { return a < 0 ? -a : a; }
template<class T> inline T dtSqr(T a) { return a*a; }
template<class T> inline T dtClamp(T v, T mn, T mx) { return v < mn ? mn : (v > mx ? mx : v); }
float dtSqrt(float x);
inline void dtVcross(float* dest, const float* v1, const float* v2)
{
dest[0] = v1[1]*v2[2] - v1[2]*v2[1];
dest[1] = v1[2]*v2[0] - v1[0]*v2[2];
dest[2] = v1[0]*v2[1] - v1[1]*v2[0];
}
inline float dtVdot(const float* v1, const float* v2)
{
return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
}
inline void dtVmad(float* dest, const float* v1, const float* v2, const float s)
{
dest[0] = v1[0]+v2[0]*s;
dest[1] = v1[1]+v2[1]*s;
dest[2] = v1[2]+v2[2]*s;
}
inline void dtVlerp(float* dest, const float* v1, const float* v2, const float t)
{
dest[0] = v1[0]+(v2[0]-v1[0])*t;
dest[1] = v1[1]+(v2[1]-v1[1])*t;
dest[2] = v1[2]+(v2[2]-v1[2])*t;
}
inline void dtVadd(float* dest, const float* v1, const float* v2)
{
dest[0] = v1[0]+v2[0];
dest[1] = v1[1]+v2[1];
dest[2] = v1[2]+v2[2];
}
inline void dtVsub(float* dest, const float* v1, const float* v2)
{
dest[0] = v1[0]-v2[0];
dest[1] = v1[1]-v2[1];
dest[2] = v1[2]-v2[2];
}
inline void dtVscale(float* dest, const float* v, const float t)
{
dest[0] = v[0]*t;
dest[1] = v[1]*t;
dest[2] = v[2]*t;
}
inline void dtVmin(float* mn, const float* v)
{
mn[0] = dtMin(mn[0], v[0]);
mn[1] = dtMin(mn[1], v[1]);
mn[2] = dtMin(mn[2], v[2]);
}
inline void dtVmax(float* mx, const float* v)
{
mx[0] = dtMax(mx[0], v[0]);
mx[1] = dtMax(mx[1], v[1]);
mx[2] = dtMax(mx[2], v[2]);
}
inline void dtVset(float* dest, const float x, const float y, const float z)
{
dest[0] = x; dest[1] = y; dest[2] = z;
}
inline void dtVcopy(float* dest, const float* a)
{
dest[0] = a[0];
dest[1] = a[1];
dest[2] = a[2];
}
inline float dtVlen(const float* v)
{
return dtSqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
}
inline float dtVlenSqr(const float* v)
{
return v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
}
inline float dtVdist(const float* v1, const float* v2)
{
const float dx = v2[0] - v1[0];
const float dy = v2[1] - v1[1];
const float dz = v2[2] - v1[2];
return dtSqrt(dx*dx + dy*dy + dz*dz);
}
inline float dtVdistSqr(const float* v1, const float* v2)
{
const float dx = v2[0] - v1[0];
const float dy = v2[1] - v1[1];
const float dz = v2[2] - v1[2];
return dx*dx + dy*dy + dz*dz;
}
inline float dtVdist2D(const float* v1, const float* v2)
{
const float dx = v2[0] - v1[0];
const float dz = v2[2] - v1[2];
return dtSqrt(dx*dx + dz*dz);
}
inline float dtVdist2DSqr(const float* v1, const float* v2)
{
const float dx = v2[0] - v1[0];
const float dz = v2[2] - v1[2];
return dx*dx + dz*dz;
}
inline void dtVnormalize(float* v)
{
float d = 1.0f / dtSqrt(dtSqr(v[0]) + dtSqr(v[1]) + dtSqr(v[2]));
v[0] *= d;
v[1] *= d;
v[2] *= d;
}
inline bool dtVequal(const float* p0, const float* p1)
{
static const float thr = dtSqr(1.0f/16384.0f);
const float d = dtVdistSqr(p0, p1);
return d < thr;
}
inline unsigned int dtNextPow2(unsigned int v)
{
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v++;
return v;
}
inline unsigned int dtIlog2(unsigned int v)
{
unsigned int r;
unsigned int shift;
r = (v > 0xffff) << 4; v >>= r;
shift = (v > 0xff) << 3; v >>= shift; r |= shift;
shift = (v > 0xf) << 2; v >>= shift; r |= shift;
shift = (v > 0x3) << 1; v >>= shift; r |= shift;
r |= (v >> 1);
return r;
}
inline int dtAlign4(int x) { return (x+3) & ~3; }
inline int dtOppositeTile(int side) { return (side+4) & 0x7; }
inline float dtVdot2D(const float* u, const float* v)
{
return u[0]*v[0] + u[2]*v[2];
}
inline float dtVperp2D(const float* u, const float* v)
{
return u[2]*v[0] - u[0]*v[2];
}
inline float dtTriArea2D(const float* a, const float* b, const float* c)
{
const float abx = b[0] - a[0];
const float abz = b[2] - a[2];
const float acx = c[0] - a[0];
const float acz = c[2] - a[2];
return acx*abz - abx*acz;
}
inline bool dtOverlapQuantBounds(const unsigned short amin[3], const unsigned short amax[3],
const unsigned short bmin[3], const unsigned short bmax[3])
{
bool overlap = true;
overlap = (amin[0] > bmax[0] || amax[0] < bmin[0]) ? false : overlap;
overlap = (amin[1] > bmax[1] || amax[1] < bmin[1]) ? false : overlap;
overlap = (amin[2] > bmax[2] || amax[2] < bmin[2]) ? false : overlap;
return overlap;
}
inline bool dtOverlapBounds(const float* amin, const float* amax,
const float* bmin, const float* bmax)
{
bool overlap = true;
overlap = (amin[0] > bmax[0] || amax[0] < bmin[0]) ? false : overlap;
overlap = (amin[1] > bmax[1] || amax[1] < bmin[1]) ? false : overlap;
overlap = (amin[2] > bmax[2] || amax[2] < bmin[2]) ? false : overlap;
return overlap;
}
void dtClosestPtPointTriangle(float* closest, const float* p,
const float* a, const float* b, const float* c);
bool dtClosestHeightPointTriangle(const float* p, const float* a, const float* b, const float* c, float& h);
bool dtIntersectSegmentPoly2D(const float* p0, const float* p1,
const float* verts, int nverts,
float& tmin, float& tmax,
int& segMin, int& segMax);
bool dtPointInPolygon(const float* pt, const float* verts, const int nverts);
bool dtDistancePtPolyEdgesSqr(const float* pt, const float* verts, const int nverts,
float* ed, float* et);
float dtDistancePtSegSqr2D(const float* pt, const float* p, const float* q, float& t);
void dtCalcPolyCenter(float* tc, const unsigned short* idx, int nidx, const float* verts);
bool dtOverlapPolyPoly2D(const float* polya, const int npolya,
const float* polyb, const int npolyb);
#endif // DETOURCOMMON_H

View File

@@ -1,428 +0,0 @@
//
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#ifndef DETOURNAVMESH_H
#define DETOURNAVMESH_H
#include "DetourAlloc.h"
#ifdef WIN32
typedef unsigned __int64 uint64;
#else
#include <stdint.h>
#ifndef uint64_t
#ifdef __linux__
#include <linux/types.h>
#endif
#endif
typedef uint64_t uint64;
#endif
// Note: If you want to use 64-bit refs, change the types of both dtPolyRef & dtTileRef.
// It is also recommended to change dtHashRef() to proper 64-bit hash too.
// Reference to navigation polygon.
typedef uint64 dtPolyRef;
// Reference to navigation mesh tile.
typedef uint64 dtTileRef;
// Maximum number of vertices per navigation polygon.
static const int DT_VERTS_PER_POLYGON = 6;
static const int DT_NAVMESH_MAGIC = 'D'<<24 | 'N'<<16 | 'A'<<8 | 'V'; //'DNAV';
static const int DT_NAVMESH_VERSION = 6;
static const int DT_NAVMESH_STATE_MAGIC = 'D'<<24 | 'N'<<16 | 'M'<<8 | 'S'; //'DNMS';
static const int DT_NAVMESH_STATE_VERSION = 1;
static const unsigned short DT_EXT_LINK = 0x8000;
static const unsigned int DT_NULL_LINK = 0xffffffff;
static const unsigned int DT_OFFMESH_CON_BIDIR = 1;
static const int DT_MAX_AREAS = 64;
static const int STATIC_SALT_BITS = 12;
static const int STATIC_TILE_BITS = 21;
static const int STATIC_POLY_BITS = 31;
// we cannot have over 31 bits for either tile nor poly
// without changing polyCount to use 64bits too.
// Flags for addTile
enum dtTileFlags
{
DT_TILE_FREE_DATA = 0x01, // Navmesh owns the tile memory and should free it.
};
// Flags returned by findStraightPath().
enum dtStraightPathFlags
{
DT_STRAIGHTPATH_START = 0x01, // The vertex is the start position.
DT_STRAIGHTPATH_END = 0x02, // The vertex is the end position.
DT_STRAIGHTPATH_OFFMESH_CONNECTION = 0x04, // The vertex is start of an off-mesh link.
};
// Flags describing polygon properties.
enum dtPolyTypes
{
DT_POLYTYPE_GROUND = 0, // Regular ground polygons.
DT_POLYTYPE_OFFMESH_CONNECTION = 1, // Off-mesh connections.
};
enum dtStatus
{
DT_FAILURE = 0, // Operation failed.
DT_FAILURE_DATA_MAGIC,
DT_FAILURE_DATA_VERSION,
DT_FAILURE_OUT_OF_MEMORY,
DT_SUCCESS, // Operation succeed.
DT_IN_PROGRESS, // Operation still in progress.
};
// Structure describing the navigation polygon data.
struct dtPoly
{
unsigned int firstLink; // Index to first link in linked list.
unsigned short verts[DT_VERTS_PER_POLYGON]; // Indices to vertices of the poly.
unsigned short neis[DT_VERTS_PER_POLYGON]; // Refs to neighbours of the poly.
unsigned short flags; // Flags (see dtPolyFlags).
unsigned char vertCount; // Number of vertices.
unsigned char areaAndtype; // Bit packed: Area ID of the polygon, and Polygon type, see dtPolyTypes..
inline void setArea(unsigned char a) { areaAndtype = (areaAndtype & 0xc0) | (a & 0x3f); }
inline void setType(unsigned char t) { areaAndtype = (areaAndtype & 0x3f) | (t << 6); }
inline unsigned char getArea() const { return areaAndtype & 0x3f; }
inline unsigned char getType() const { return areaAndtype >> 6; }
};
// Stucture describing polygon detail triangles.
struct dtPolyDetail
{
unsigned int vertBase; // Offset to detail vertex array.
unsigned int triBase; // Offset to detail triangle array.
unsigned char vertCount; // Number of vertices in the detail mesh.
unsigned char triCount; // Number of triangles.
};
// Stucture describing a link to another polygon.
struct dtLink
{
dtPolyRef ref; // Neighbour reference.
unsigned int next; // Index to next link.
unsigned char edge; // Index to polygon edge which owns this link.
unsigned char side; // If boundary link, defines on which side the link is.
unsigned char bmin, bmax; // If boundary link, defines the sub edge area.
};
struct dtBVNode
{
unsigned short bmin[3], bmax[3]; // BVnode bounds
int i; // Index to item or if negative, escape index.
};
struct dtOffMeshConnection
{
float pos[6]; // Both end point locations.
float rad; // Link connection radius.
unsigned short poly; // Poly Id
unsigned char flags; // Link flags
unsigned char side; // End point side.
unsigned int userId; // User ID to identify this connection.
};
struct dtMeshHeader
{
int magic; // Magic number, used to identify the data.
int version; // Data version number.
int x, y; // Location of the time on the grid.
unsigned int userId; // User ID of the tile.
int polyCount; // Number of polygons in the tile.
int vertCount; // Number of vertices in the tile.
int maxLinkCount; // Number of allocated links.
int detailMeshCount; // Number of detail meshes.
int detailVertCount; // Number of detail vertices.
int detailTriCount; // Number of detail triangles.
int bvNodeCount; // Number of BVtree nodes.
int offMeshConCount; // Number of Off-Mesh links.
int offMeshBase; // Index to first polygon which is Off-Mesh link.
float walkableHeight; // Height of the agent.
float walkableRadius; // Radius of the agent
float walkableClimb; // Max climb height of the agent.
float bmin[3], bmax[3]; // Bounding box of the tile.
float bvQuantFactor; // BVtree quantization factor (world to bvnode coords)
};
struct dtMeshTile
{
unsigned int salt; // Counter describing modifications to the tile.
unsigned int linksFreeList; // Index to next free link.
dtMeshHeader* header; // Pointer to tile header.
dtPoly* polys; // Pointer to the polygons (will be updated when tile is added).
float* verts; // Pointer to the vertices (will be updated when tile added).
dtLink* links; // Pointer to the links (will be updated when tile added).
dtPolyDetail* detailMeshes; // Pointer to detail meshes (will be updated when tile added).
float* detailVerts; // Pointer to detail vertices (will be updated when tile added).
unsigned char* detailTris; // Pointer to detail triangles (will be updated when tile added).
dtBVNode* bvTree; // Pointer to BVtree nodes (will be updated when tile added).
dtOffMeshConnection* offMeshCons; // Pointer to Off-Mesh links. (will be updated when tile added).
unsigned char* data; // Pointer to tile data.
int dataSize; // Size of the tile data.
int flags; // Tile flags, see dtTileFlags.
dtMeshTile* next; // Next free tile or, next tile in spatial grid.
};
struct dtNavMeshParams
{
float orig[3]; // Origin of the nav mesh tile space.
float tileWidth, tileHeight; // Width and height of each tile.
int maxTiles; // Maximum number of tiles the navmesh can contain.
int maxPolys; // Maximum number of polygons each tile can contain.
};
class dtNavMesh
{
public:
dtNavMesh();
~dtNavMesh();
// Initializes the nav mesh for tiled use.
// Params:
// params - (in) navmesh initialization params, see dtNavMeshParams.
// Returns: True if succeed, else false.
dtStatus init(const dtNavMeshParams* params);
// Initializes the nav mesh for single tile use.
// Params:
// data - (in) Data of the new tile mesh.
// dataSize - (in) Data size of the new tile mesh.
// flags - (in) Tile flags, see dtTileFlags.
// Returns: True if succeed, else false.
dtStatus init(unsigned char* data, const int dataSize, const int flags);
// Returns pointer to navmesh initialization params.
const dtNavMeshParams* getParams() const;
// Adds new tile into the navmesh.
// The add will fail if the data is in wrong format,
// there is not enough tiles left, or if there is a tile already at the location.
// Params:
// data - (in) Data of the new tile mesh.
// dataSize - (in) Data size of the new tile mesh.
// flags - (in) Tile flags, see dtTileFlags.
// lastRef - (in,optional) Last tile ref, the tile will be restored so that
// the reference (as well as poly references) will be the same. Default: 0.
// result - (out,optional) tile ref if the tile was succesfully added.
dtStatus addTile(unsigned char* data, int dataSize, int flags, dtTileRef lastRef, dtTileRef* result);
// Removes specified tile.
// Params:
// ref - (in) Reference to the tile to remove.
// data - (out) Data associated with deleted tile.
// dataSize - (out) Size of the data associated with deleted tile.
dtStatus removeTile(dtTileRef ref, unsigned char** data, int* dataSize);
// Calculates tile location based in input world position.
// Params:
// pos - (in) world position of the query.
// tx - (out) tile x location.
// ty - (out) tile y location.
void calcTileLoc(const float* pos, int* tx, int* ty) const;
// Returns pointer to tile at specified location.
// Params:
// x,y - (in) Location of the tile to get.
// Returns: pointer to tile if tile exists or 0 tile does not exists.
const dtMeshTile* getTileAt(int x, int y) const;
// Returns reference to tile at specified location.
// Params:
// x,y - (in) Location of the tile to get.
// Returns: reference to tile if tile exists or 0 tile does not exists.
dtTileRef getTileRefAt(int x, int y) const;
// Returns tile references of a tile based on tile pointer.
dtTileRef getTileRef(const dtMeshTile* tile) const;
// Returns tile based on references.
const dtMeshTile* getTileByRef(dtTileRef ref) const;
// Returns max number of tiles.
int getMaxTiles() const;
// Returns pointer to tile in the tile array.
// Params:
// i - (in) Index to the tile to retrieve, max index is getMaxTiles()-1.
// Returns: Pointer to specified tile.
const dtMeshTile* getTile(int i) const;
// Returns pointer to tile and polygon pointed by the polygon reference.
// Params:
// ref - (in) reference to a polygon.
// tile - (out) pointer to the tile containing the polygon.
// poly - (out) pointer to the polygon.
dtStatus getTileAndPolyByRef(const dtPolyRef ref, const dtMeshTile** tile, const dtPoly** poly) const;
// Returns pointer to tile and polygon pointed by the polygon reference.
// Note: this function does not check if 'ref' s valid, and is thus faster. Use only with valid refs!
// Params:
// ref - (in) reference to a polygon.
// tile - (out) pointer to the tile containing the polygon.
// poly - (out) pointer to the polygon.
void getTileAndPolyByRefUnsafe(const dtPolyRef ref, const dtMeshTile** tile, const dtPoly** poly) const;
// Returns true if polygon reference points to valid data.
bool isValidPolyRef(dtPolyRef ref) const;
// Returns base poly id for specified tile, polygon refs can be deducted from this.
dtPolyRef getPolyRefBase(const dtMeshTile* tile) const;
// Returns start and end location of an off-mesh link polygon.
// Params:
// prevRef - (in) ref to the polygon before the link (used to select direction).
// polyRef - (in) ref to the off-mesh link polygon.
// startPos[3] - (out) start point of the link.
// endPos[3] - (out) end point of the link.
// Returns: true if link is found.
dtStatus getOffMeshConnectionPolyEndPoints(dtPolyRef prevRef, dtPolyRef polyRef, float* startPos, float* endPos) const;
// Returns pointer to off-mesh connection based on polyref, or null if ref not valid.
const dtOffMeshConnection* getOffMeshConnectionByRef(dtPolyRef ref) const;
// Sets polygon flags.
dtStatus setPolyFlags(dtPolyRef ref, unsigned short flags);
// Return polygon flags.
dtStatus getPolyFlags(dtPolyRef ref, unsigned short* resultFlags) const;
// Set polygon type.
dtStatus setPolyArea(dtPolyRef ref, unsigned char area);
// Return polygon area type.
dtStatus getPolyArea(dtPolyRef ref, unsigned char* resultArea) const;
// Returns number of bytes required to store tile state.
int getTileStateSize(const dtMeshTile* tile) const;
// Stores tile state to buffer.
dtStatus storeTileState(const dtMeshTile* tile, unsigned char* data, const int maxDataSize) const;
// Restores tile state.
dtStatus restoreTileState(dtMeshTile* tile, const unsigned char* data, const int maxDataSize);
// Encodes a tile id.
inline dtPolyRef encodePolyId(unsigned int salt, unsigned int it, unsigned int ip) const
{
return ((dtPolyRef)salt << (m_polyBits+m_tileBits)) | ((dtPolyRef)it << m_polyBits) | (dtPolyRef)ip;
}
// Decodes a tile id.
inline void decodePolyId(dtPolyRef ref, unsigned int& salt, unsigned int& it, unsigned int& ip) const
{
const dtPolyRef saltMask = ((dtPolyRef)1<<m_saltBits)-1;
const dtPolyRef tileMask = ((dtPolyRef)1<<m_tileBits)-1;
const dtPolyRef polyMask = ((dtPolyRef)1<<m_polyBits)-1;
salt = (unsigned int)((ref >> (m_polyBits+m_tileBits)) & saltMask);
it = (unsigned int)((ref >> m_polyBits) & tileMask);
ip = (unsigned int)(ref & polyMask);
}
// Decodes a tile salt.
inline unsigned int decodePolyIdSalt(dtPolyRef ref) const
{
const dtPolyRef saltMask = ((dtPolyRef)1<<m_saltBits)-1;
return (unsigned int)((ref >> (m_polyBits+m_tileBits)) & saltMask);
}
// Decodes a tile id.
inline unsigned int decodePolyIdTile(dtPolyRef ref) const
{
const dtPolyRef tileMask = ((dtPolyRef)1<<m_tileBits)-1;
return (unsigned int)((ref >> m_polyBits) & tileMask);
}
// Decodes a poly id.
inline unsigned int decodePolyIdPoly(dtPolyRef ref) const
{
const dtPolyRef polyMask = ((dtPolyRef)1<<m_polyBits)-1;
return (unsigned int)(ref & polyMask);
}
private:
// Returns pointer to tile in the tile array.
dtMeshTile* getTile(int i);
// Returns neighbour tile based on side.
dtMeshTile* getNeighbourTileAt(int x, int y, int side) const;
// Returns all polygons in neighbour tile based on portal defined by the segment.
int findConnectingPolys(const float* va, const float* vb,
const dtMeshTile* tile, int side,
dtPolyRef* con, float* conarea, int maxcon) const;
// Builds internal polygons links for a tile.
void connectIntLinks(dtMeshTile* tile);
// Builds internal polygons links for a tile.
void connectIntOffMeshLinks(dtMeshTile* tile);
// Builds external polygon links for a tile.
void connectExtLinks(dtMeshTile* tile, dtMeshTile* target, int side);
// Builds external polygon links for a tile.
void connectExtOffMeshLinks(dtMeshTile* tile, dtMeshTile* target, int side);
// Removes external links at specified side.
void unconnectExtLinks(dtMeshTile* tile, int side);
// TODO: These methods are duplicates from dtNavMeshQuery, but are needed for off-mesh connection finding.
// Queries polygons within a tile.
int queryPolygonsInTile(const dtMeshTile* tile, const float* qmin, const float* qmax,
dtPolyRef* polys, const int maxPolys) const;
// Find nearest polygon within a tile.
dtPolyRef findNearestPolyInTile(const dtMeshTile* tile, const float* center,
const float* extents, float* nearestPt) const;
// Returns closest point on polygon.
dtStatus closestPointOnPolyInTile(const dtMeshTile* tile, unsigned int ip,
const float* pos, float* closest) const;
dtNavMeshParams m_params; // Current initialization params. TODO: do not store this info twice.
float m_orig[3]; // Origin of the tile (0,0)
float m_tileWidth, m_tileHeight; // Dimensions of each tile.
int m_maxTiles; // Max number of tiles.
int m_tileLutSize; // Tile hash lookup size (must be pot).
int m_tileLutMask; // Tile hash lookup mask.
dtMeshTile** m_posLookup; // Tile hash lookup.
dtMeshTile* m_nextFree; // Freelist of tiles.
dtMeshTile* m_tiles; // List of tiles.
unsigned int m_saltBits; // Number of salt bits in the tile ID.
unsigned int m_tileBits; // Number of tile bits in the tile ID.
unsigned int m_polyBits; // Number of poly bits in the tile ID.
};
// Helper function to allocate navmesh class using Detour allocator.
dtNavMesh* dtAllocNavMesh();
void dtFreeNavMesh(dtNavMesh* navmesh);
#endif // DETOURNAVMESH_H

View File

@@ -1,79 +0,0 @@
//
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#ifndef DETOURNAVMESHBUILDER_H
#define DETOURNAVMESHBUILDER_H
#include "DetourAlloc.h"
// The units of the parameters are specified in parenthesis as follows:
// (vx) voxels, (wu) world units
struct dtNavMeshCreateParams
{
// Navmesh vertices.
const unsigned short* verts; // Array of vertices, each vertex has 3 components. (vx).
int vertCount; // Vertex count
// Navmesh polygons
const unsigned short* polys; // Array of polygons, uses same format as rcPolyMesh.
const unsigned short* polyFlags; // Array of flags per polygon.
const unsigned char* polyAreas; // Array of area ids per polygon.
int polyCount; // Number of polygons
int nvp; // Number of verts per polygon.
// Navmesh Detail
const unsigned int* detailMeshes; // Detail meshes, uses same format as rcPolyMeshDetail.
const float* detailVerts; // Detail mesh vertices, uses same format as rcPolyMeshDetail (wu).
int detailVertsCount; // Total number of detail vertices
const unsigned char* detailTris; // Array of detail tris per detail mesh.
int detailTriCount; // Total number of detail triangles.
// Off-Mesh Connections.
const float* offMeshConVerts; // Off-mesh connection vertices (wu).
const float* offMeshConRad; // Off-mesh connection radii (wu).
const unsigned short* offMeshConFlags; // Off-mesh connection flags.
const unsigned char* offMeshConAreas; // Off-mesh connection area ids.
const unsigned char* offMeshConDir; // Off-mesh connection direction flags (1 = bidir, 0 = oneway).
const unsigned int* offMeshConUserID; // Off-mesh connection user id (optional).
int offMeshConCount; // Number of off-mesh connections
// Tile location
unsigned int userId; // User ID bound to the tile.
int tileX, tileY; // Tile location (tile coords).
float bmin[3], bmax[3]; // Tile bounds (wu).
// Settings
float walkableHeight; // Agent height (wu).
float walkableRadius; // Agent radius (wu).
float walkableClimb; // Agent max climb (wu).
float cs; // Cell size (xz) (wu).
float ch; // Cell height (y) (wu).
int tileSize; // Tile size (width & height) (vx).
int tileLayer;
bool buildBvTree;
};
// Build navmesh data from given input data.
bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, int* outDataSize);
// Swaps endianess of navmesh header.
bool dtNavMeshHeaderSwapEndian(unsigned char* data, const int dataSize);
// Swaps endianess of the navmesh data. This function assumes that the header is in correct
// endianess already. Call dtNavMeshHeaderSwapEndian() first on the data if the data is
// assumed to be in wrong endianess to start with. If converting from native endianess to foreign,
// call dtNavMeshHeaderSwapEndian() after the data has been swapped.
bool dtNavMeshDataSwapEndian(unsigned char* data, const int dataSize);
#endif // DETOURNAVMESHBUILDER_H

View File

@@ -1,407 +0,0 @@
//
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#ifndef DETOURNAVMESHQUERY_H
#define DETOURNAVMESHQUERY_H
#include "DetourNavMesh.h"
// Define DT_VIRTUAL_QUERYFILTER if you wish to derive a custom filter from dtQueryFilter.
// On certain platforms indirect or virtual function call is expensive. The default
// setting is to use non-virtual functions, the actualy implementations of the functions
// are declared as inline for maximum speed.
//#define DT_VIRTUAL_QUERYFILTER 1
// Class for polygon filtering and cost calculation during query operations.
// - It is possible to derive a custom query filter from dtQueryFilter by overriding
// the virtual functions passFilter() and getCost().
// - Both functions should be as fast as possible. Use cached local copy of data
// instead of accessing your own objects where possible.
// - You do not need to adhere to the flags and cost logic provided by the default
// implementation.
// - In order for the A* to work properly, the cost should be proportional to
// the travel distance. Using cost modifier less than 1.0 is likely to lead
// to problems during pathfinding.
class dtQueryFilter
{
float m_areaCost[DT_MAX_AREAS]; // Array storing cost per area type, used by default implementation.
unsigned short m_includeFlags; // Include poly flags, used by default implementation.
unsigned short m_excludeFlags; // Exclude poly flags, used by default implementation.
public:
dtQueryFilter();
// Returns true if the polygon is can visited.
// Params:
// ref - (in) reference to the polygon test.
// tile - (in) pointer to the tile of the polygon test.
// poly - (in) pointer to the polygon test.
#ifdef DT_VIRTUAL_QUERYFILTER
virtual bool passFilter(const dtPolyRef ref,
const dtMeshTile* tile,
const dtPoly* poly) const;
#else
bool passFilter(const dtPolyRef ref,
const dtMeshTile* tile,
const dtPoly* poly) const;
#endif
// Returns cost to travel from 'pa' to 'pb'.'
// The segment is fully contained inside 'cur'.
// 'pa' lies on the edge between 'prev' and 'cur',
// 'pb' lies on the edge between 'cur' and 'next'.
// Params:
// pa - (in) segment start position.
// pb - (in) segment end position.
// prevRef, prevTile, prevPoly - (in) data describing the previous polygon, can be null.
// curRef, curTile, curPoly - (in) data describing the current polygon.
// nextRef, nextTile, nextPoly - (in) data describing the next polygon, can be null.
#ifdef DT_VIRTUAL_QUERYFILTER
virtual float getCost(const float* pa, const float* pb,
const dtPolyRef prevRef, const dtMeshTile* prevTile, const dtPoly* prevPoly,
const dtPolyRef curRef, const dtMeshTile* curTile, const dtPoly* curPoly,
const dtPolyRef nextRef, const dtMeshTile* nextTile, const dtPoly* nextPoly) const;
#else
float getCost(const float* pa, const float* pb,
const dtPolyRef prevRef, const dtMeshTile* prevTile, const dtPoly* prevPoly,
const dtPolyRef curRef, const dtMeshTile* curTile, const dtPoly* curPoly,
const dtPolyRef nextRef, const dtMeshTile* nextTile, const dtPoly* nextPoly) const;
#endif
// Getters and setters for the default implementation data.
inline float getAreaCost(const int i) const { return m_areaCost[i]; }
inline void setAreaCost(const int i, const float cost) { m_areaCost[i] = cost; }
inline unsigned short getIncludeFlags() const { return m_includeFlags; }
inline void setIncludeFlags(const unsigned short flags) { m_includeFlags = flags; }
inline unsigned short getExcludeFlags() const { return m_excludeFlags; }
inline void setExcludeFlags(const unsigned short flags) { m_excludeFlags = flags; }
};
class dtNavMeshQuery
{
public:
dtNavMeshQuery();
~dtNavMeshQuery();
// Initializes the nav mesh query.
// Params:
// nav - (in) pointer to navigation mesh data.
// maxNodes - (in) Maximum number of search nodes to use (max 65536).
// Returns: True if succeed, else false.
dtStatus init(const dtNavMesh* nav, const int maxNodes);
// Finds the nearest navigation polygon around the center location.
// Params:
// center[3] - (in) The center of the search box.
// extents[3] - (in) The extents of the search box.
// filter - (in) path polygon filter.
// nearestRef - (out) Reference to the nearest polygon.
// nearestPt[3] - (out, opt) The nearest point on found polygon, null if not needed.
// Returns: Reference identifier for the polygon, or 0 if no polygons found.
dtStatus findNearestPoly(const float* center, const float* extents,
const dtQueryFilter* filter,
dtPolyRef* nearestRef, float* nearestPt) const;
// Returns polygons which overlap the query box.
// Params:
// center[3] - (in) the center of the search box.
// extents[3] - (in) the extents of the search box.
// filter - (in) path polygon filter.
// polys - (out) array holding the search result.
// polyCount - (out) Number of polygons in search result array.
// maxPolys - (in) The max number of polygons the polys array can hold.
dtStatus queryPolygons(const float* center, const float* extents,
const dtQueryFilter* filter,
dtPolyRef* polys, int* polyCount, const int maxPolys) const;
// Finds path from start polygon to end polygon.
// If target polygon canno be reached through the navigation graph,
// the last node on the array is nearest node to the end polygon.
// Start end end positions are needed to calculate more accurate
// traversal cost at start end end polygons.
// Params:
// startRef - (in) ref to path start polygon.
// endRef - (in) ref to path end polygon.
// startPos[3] - (in) Path start location.
// endPos[3] - (in) Path end location.
// filter - (in) path polygon filter.
// path - (out) array holding the search result.
// pathCount - (out) Number of polygons in search result array.
// maxPath - (in) The max number of polygons the path array can hold. Must be at least 1.
dtStatus findPath(dtPolyRef startRef, dtPolyRef endRef,
const float* startPos, const float* endPos,
const dtQueryFilter* filter,
dtPolyRef* path, int* pathCount, const int maxPath) const;
// Intializes sliced path find query.
// Note 1: calling any other dtNavMeshQuery method before calling findPathEnd()
// may results in corrupted data!
// Note 2: The pointer to filter is store, and used in subsequent
// calls to updateSlicedFindPath().
// Params:
// startRef - (in) ref to path start polygon.
// endRef - (in) ref to path end polygon.
// startPos[3] - (in) Path start location.
// endPos[3] - (in) Path end location.
// filter - (in) path polygon filter.
dtStatus initSlicedFindPath(dtPolyRef startRef, dtPolyRef endRef,
const float* startPos, const float* endPos,
const dtQueryFilter* filter);
// Updates sliced path find query.
// Params:
// maxIter - (in) max number of iterations to update.
// Returns: Path query state.
dtStatus updateSlicedFindPath(const int maxIter);
// Finalizes sliced path find query and returns found path.
// path - (out) array holding the search result.
// pathCount - (out) Number of polygons in search result array.
// maxPath - (in) The max number of polygons the path array can hold.
dtStatus finalizeSlicedFindPath(dtPolyRef* path, int* pathCount, const int maxPath);
// Finalizes partial sliced path find query and returns path to the furthest
// polygon on the existing path that was visited during the search.
// existing - (out) Array of polygons in the existing path.
// existingSize - (out) Number of polygons in existing path array.
// path - (out) array holding the search result.
// pathCount - (out) Number of polygons in search result array.
// maxPath - (in) The max number of polygons the path array can hold.
dtStatus finalizeSlicedFindPathPartial(const dtPolyRef* existing, const int existingSize,
dtPolyRef* path, int* pathCount, const int maxPath);
// Finds a straight path from start to end locations within the corridor
// described by the path polygons.
// Start and end locations will be clamped on the corridor.
// The returned polygon references are point to polygon which was entered when
// a path point was added. For the end point, zero will be returned. This allows
// to match for example off-mesh link points to their representative polygons.
// Params:
// startPos[3] - (in) Path start location.
// endPo[3] - (in) Path end location.
// path - (in) Array of connected polygons describing the corridor.
// pathSize - (in) Number of polygons in path array.
// straightPath - (out) Points describing the straight path.
// straightPathFlags - (out, opt) Flags describing each point type, see dtStraightPathFlags.
// straightPathRefs - (out, opt) References to polygons at point locations.
// straightPathCount - (out) Number of points in the path.
// maxStraightPath - (in) The max number of points the straight path array can hold. Must be at least 1.
dtStatus findStraightPath(const float* startPos, const float* endPos,
const dtPolyRef* path, const int pathSize,
float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs,
int* straightPathCount, const int maxStraightPath) const;
// Moves from startPos to endPos constrained to the navmesh.
// If the endPos is reachable, the resultPos will be endPos,
// or else the resultPos will be the nearest point in navmesh.
// Note: The resulting point is not projected to the ground, use getPolyHeight() to get height.
// Note: The algorithm is optimized for small delta movement and small number of polygons.
// Params:
// startRef - (in) ref to the polygon where startPos lies.
// startPos[3] - (in) start position of the mover.
// endPos[3] - (in) desired end position of the mover.
// filter - (in) path polygon filter.
// resultPos[3] - (out) new position of the mover.
// visited - (out) array of visited polygons.
// visitedCount - (out) Number of entries in the visited array.
// maxVisitedSize - (in) max number of polygons in the visited array.
dtStatus moveAlongSurface(dtPolyRef startRef, const float* startPos, const float* endPos,
const dtQueryFilter* filter,
float* resultPos, dtPolyRef* visited, int* visitedCount, const int maxVisitedSize) const;
// Casts 'walkability' ray along the navmesh surface from startPos towards the endPos.
// Params:
// startRef - (in) ref to the polygon where the start lies.
// startPos[3] - (in) start position of the query.
// endPos[3] - (in) end position of the query.
// t - (out) hit parameter along the segment, FLT_MAX if no hit.
// hitNormal[3] - (out) normal of the nearest hit.
// filter - (in) path polygon filter.
// path - (out,opt) visited path polygons.
// pathCount - (out,opt) Number of polygons visited.
// maxPath - (in) max number of polygons in the path array.
dtStatus raycast(dtPolyRef startRef, const float* startPos, const float* endPos,
const dtQueryFilter* filter,
float* t, float* hitNormal, dtPolyRef* path, int* pathCount, const int maxPath) const;
// Returns distance to nearest wall from the specified location.
// Params:
// startRef - (in) ref to the polygon where the center lies.
// centerPos[3] - (in) center if the query circle.
// maxRadius - (in) max search radius.
// filter - (in) path polygon filter.
// hitDist - (out) distance to nearest wall from the test location.
// hitPos[3] - (out) location of the nearest hit.
// hitNormal[3] - (out) normal of the nearest hit.
dtStatus findDistanceToWall(dtPolyRef startRef, const float* centerPos, const float maxRadius,
const dtQueryFilter* filter,
float* hitDist, float* hitPos, float* hitNormal) const;
// Finds polygons found along the navigation graph which touch the specified circle.
// Params:
// startRef - (in) ref to the polygon where the search starts.
// centerPos[3] - (in) center if the query circle.
// radius - (in) radius of the query circle.
// filter - (in) path polygon filter.
// resultRef - (out, opt) refs to the polygons touched by the circle.
// resultParent - (out, opt) parent of each result polygon.
// resultCost - (out, opt) search cost at each result polygon.
// resultCount - (out, opt) Number of results.
// maxResult - (int) maximum capacity of search results.
dtStatus findPolysAroundCircle(dtPolyRef startRef, const float* centerPos, const float radius,
const dtQueryFilter* filter,
dtPolyRef* resultRef, dtPolyRef* resultParent, float* resultCost,
int* resultCount, const int maxResult) const;
// Finds polygons found along the navigation graph which touch the convex polygon shape.
// Params:
// startRef - (in) ref to the polygon where the search starts.
// verts[3*n] - (in) vertices describing convex polygon shape (CCW).
// nverts - (in) number of vertices in the polygon.
// filter - (in) path polygon filter.
// resultRef - (out, opt) refs to the polygons touched by the circle.
// resultParent - (out, opt) parent of each result polygon.
// resultCost - (out, opt) search cost at each result polygon.
// resultCount - (out) number of results.
// maxResult - (int) maximum capacity of search results.
dtStatus findPolysAroundShape(dtPolyRef startRef, const float* verts, const int nverts,
const dtQueryFilter* filter,
dtPolyRef* resultRef, dtPolyRef* resultParent, float* resultCost,
int* resultCount, const int maxResult) const;
// Finds non-overlapping local neighbourhood around center location.
// Note: The algorithm is optimized for small query radius and small number of polygons.
// Params:
// startRef - (in) ref to the polygon where the search starts.
// centerPos[3] - (in) center if the query circle.
// radius - (in) radius of the query circle.
// filter - (in) path polygon filter.
// resultRef - (out) refs to the polygons touched by the circle.
// resultParent - (out, opt) parent of each result polygon.
// resultCount - (out) number of results.
// maxResult - (int) maximum capacity of search results.
dtStatus findLocalNeighbourhood(dtPolyRef startRef, const float* centerPos, const float radius,
const dtQueryFilter* filter,
dtPolyRef* resultRef, dtPolyRef* resultParent,
int* resultCount, const int maxResult) const;
// Returns wall segments of specified polygon.
// Params:
// ref - (in) ref to the polygon.
// filter - (in) path polygon filter.
// segments[6*maxSegments] - (out) wall segments (2 endpoints per segment).
// segmentCount - (out) number of wall segments.
// maxSegments - (in) max number of segments that can be stored in 'segments'.
dtStatus getPolyWallSegments(dtPolyRef ref, const dtQueryFilter* filter,
float* segments, int* segmentCount, const int maxSegments) const;
// Returns closest point on navigation polygon.
// Uses detail polygons to find the closest point to the navigation polygon surface.
// Params:
// ref - (in) ref to the polygon.
// pos[3] - (in) the point to check.
// closest[3] - (out) closest point.
// Returns: true if closest point found.
dtStatus closestPointOnPoly(dtPolyRef ref, const float* pos, float* closest) const;
// Returns closest point on navigation polygon boundary.
// Uses the navigation polygon boundary to snap the point to poly boundary
// if it is outside the polygon. Much faster than closestPointToPoly. Does not affect height.
// Params:
// ref - (in) ref to the polygon.
// pos[3] - (in) the point to check.
// closest[3] - (out) closest point.
// Returns: true if closest point found.
dtStatus closestPointOnPolyBoundary(dtPolyRef ref, const float* pos, float* closest) const;
// Returns start and end location of an off-mesh link polygon.
// Params:
// prevRef - (in) ref to the polygon before the link (used to select direction).
// polyRef - (in) ref to the off-mesh link polygon.
// startPos[3] - (out) start point of the link.
// endPos[3] - (out) end point of the link.
// Returns: true if link is found.
dtStatus getOffMeshConnectionPolyEndPoints(dtPolyRef prevRef, dtPolyRef polyRef, float* startPos, float* endPos) const;
// Returns height of the polygon at specified location.
// Params:
// ref - (in) ref to the polygon.
// pos[3] - (in) the point where to locate the height.
// height - (out) height at the location.
// Returns: true if over polygon.
dtStatus getPolyHeight(dtPolyRef ref, const float* pos, float* height) const;
// Returns true if poly reference ins in closed list.
bool isInClosedList(dtPolyRef ref) const;
class dtNodePool* getNodePool() const { return m_nodePool; }
private:
// Returns neighbour tile based on side.
dtMeshTile* getNeighbourTileAt(int x, int y, int side) const;
// Queries polygons within a tile.
int queryPolygonsInTile(const dtMeshTile* tile, const float* qmin, const float* qmax, const dtQueryFilter* filter,
dtPolyRef* polys, const int maxPolys) const;
// Find nearest polygon within a tile.
dtPolyRef findNearestPolyInTile(const dtMeshTile* tile, const float* center, const float* extents,
const dtQueryFilter* filter, float* nearestPt) const;
// Returns closest point on polygon.
dtStatus closestPointOnPolyInTile(const dtMeshTile* tile, const dtPoly* poly, const float* pos, float* closest) const;
// Returns portal points between two polygons.
dtStatus getPortalPoints(dtPolyRef from, dtPolyRef to, float* left, float* right,
unsigned char& fromType, unsigned char& toType) const;
dtStatus getPortalPoints(dtPolyRef from, const dtPoly* fromPoly, const dtMeshTile* fromTile,
dtPolyRef to, const dtPoly* toPoly, const dtMeshTile* toTile,
float* left, float* right) const;
// Returns edge mid point between two polygons.
dtStatus getEdgeMidPoint(dtPolyRef from, dtPolyRef to, float* mid) const;
dtStatus getEdgeMidPoint(dtPolyRef from, const dtPoly* fromPoly, const dtMeshTile* fromTile,
dtPolyRef to, const dtPoly* toPoly, const dtMeshTile* toTile,
float* mid) const;
const dtNavMesh* m_nav; // Pointer to navmesh data.
struct dtQueryData
{
dtStatus status;
struct dtNode* lastBestNode;
float lastBestNodeCost;
dtPolyRef startRef, endRef;
float startPos[3], endPos[3];
const dtQueryFilter* filter;
};
dtQueryData m_query; // Sliced query state.
class dtNodePool* m_tinyNodePool; // Pointer to small node pool.
class dtNodePool* m_nodePool; // Pointer to node pool.
class dtNodeQueue* m_openList; // Pointer to open list queue.
};
// Helper function to allocate navmesh query class using Detour allocator.
dtNavMeshQuery* dtAllocNavMeshQuery();
void dtFreeNavMeshQuery(dtNavMeshQuery* query);
#endif // DETOURNAVMESHQUERY_H

View File

@@ -1,532 +0,0 @@
//
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#include "DetourObstacleAvoidance.h"
#include "DetourCommon.h"
#include "DetourAlloc.h"
#include "DetourAssert.h"
#include <string.h>
#include <math.h>
#include <float.h>
#include <new>
static int sweepCircleCircle(const float* c0, const float r0, const float* v,
const float* c1, const float r1,
float& tmin, float& tmax)
{
static const float EPS = 0.0001f;
float s[3];
dtVsub(s,c1,c0);
float r = r0+r1;
float c = dtVdot2D(s,s) - r*r;
float a = dtVdot2D(v,v);
if (a < EPS) return 0; // not moving
// Overlap, calc time to exit.
float b = dtVdot2D(v,s);
float d = b*b - a*c;
if (d < 0.0f) return 0; // no intersection.
a = 1.0f / a;
const float rd = dtSqrt(d);
tmin = (b - rd) * a;
tmax = (b + rd) * a;
return 1;
}
static int isectRaySeg(const float* ap, const float* u,
const float* bp, const float* bq,
float& t)
{
float v[3], w[3];
dtVsub(v,bq,bp);
dtVsub(w,ap,bp);
float d = dtVperp2D(u,v);
if (fabsf(d) < 1e-6f) return 0;
d = 1.0f/d;
t = dtVperp2D(v,w) * d;
if (t < 0 || t > 1) return 0;
float s = dtVperp2D(u,w) * d;
if (s < 0 || s > 1) return 0;
return 1;
}
dtObstacleAvoidanceDebugData* dtAllocObstacleAvoidanceDebugData()
{
void* mem = dtAlloc(sizeof(dtObstacleAvoidanceDebugData), DT_ALLOC_PERM);
if (!mem) return 0;
return new(mem) dtObstacleAvoidanceDebugData;
}
void dtFreeObstacleAvoidanceDebugData(dtObstacleAvoidanceDebugData* ptr)
{
if (!ptr) return;
ptr->~dtObstacleAvoidanceDebugData();
dtFree(ptr);
}
dtObstacleAvoidanceDebugData::dtObstacleAvoidanceDebugData() :
m_nsamples(0),
m_maxSamples(0),
m_vel(0),
m_ssize(0),
m_pen(0),
m_vpen(0),
m_vcpen(0),
m_spen(0),
m_tpen(0)
{
}
dtObstacleAvoidanceDebugData::~dtObstacleAvoidanceDebugData()
{
dtFree(m_vel);
dtFree(m_ssize);
dtFree(m_pen);
dtFree(m_vpen);
dtFree(m_vcpen);
dtFree(m_spen);
dtFree(m_tpen);
}
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;
}
void dtObstacleAvoidanceDebugData::reset()
{
m_nsamples = 0;
}
void dtObstacleAvoidanceDebugData::addSample(const float* vel, const float ssize, const float pen,
const float vpen, const float vcpen, const float spen, const float tpen)
{
if (m_nsamples >= m_maxSamples)
return;
dtAssert(m_vel);
dtAssert(m_ssize);
dtAssert(m_pen);
dtAssert(m_vpen);
dtAssert(m_vcpen);
dtAssert(m_spen);
dtAssert(m_tpen);
dtVcopy(&m_vel[m_nsamples*3], vel);
m_ssize[m_nsamples] = ssize;
m_pen[m_nsamples] = pen;
m_vpen[m_nsamples] = vpen;
m_vcpen[m_nsamples] = vcpen;
m_spen[m_nsamples] = spen;
m_tpen[m_nsamples] = tpen;
m_nsamples++;
}
static void normalizeArray(float* arr, const int n)
{
// Normalize penaly range.
float minPen = FLT_MAX;
float maxPen = -FLT_MAX;
for (int i = 0; i < n; ++i)
{
minPen = dtMin(minPen, arr[i]);
maxPen = dtMax(maxPen, arr[i]);
}
const float penRange = maxPen-minPen;
const float s = penRange > 0.001f ? (1.0f / penRange) : 1;
for (int i = 0; i < n; ++i)
arr[i] = dtClamp((arr[i]-minPen)*s, 0.0f, 1.0f);
}
void dtObstacleAvoidanceDebugData::normalizeSamples()
{
normalizeArray(m_pen, m_nsamples);
normalizeArray(m_vpen, m_nsamples);
normalizeArray(m_vcpen, m_nsamples);
normalizeArray(m_spen, m_nsamples);
normalizeArray(m_tpen, m_nsamples);
}
dtObstacleAvoidanceQuery* dtAllocObstacleAvoidanceQuery()
{
void* mem = dtAlloc(sizeof(dtObstacleAvoidanceQuery), DT_ALLOC_PERM);
if (!mem) return 0;
return new(mem) dtObstacleAvoidanceQuery;
}
void dtFreeObstacleAvoidanceQuery(dtObstacleAvoidanceQuery* ptr)
{
if (!ptr) return;
ptr->~dtObstacleAvoidanceQuery();
dtFree(ptr);
}
dtObstacleAvoidanceQuery::dtObstacleAvoidanceQuery() :
m_velBias(0.0f),
m_weightDesVel(0.0f),
m_weightCurVel(0.0f),
m_weightSide(0.0f),
m_weightToi(0.0f),
m_horizTime(0.0f),
m_maxCircles(0),
m_circles(0),
m_ncircles(0),
m_maxSegments(0),
m_segments(0),
m_nsegments(0)
{
}
dtObstacleAvoidanceQuery::~dtObstacleAvoidanceQuery()
{
dtFree(m_circles);
dtFree(m_segments);
}
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;
}
void dtObstacleAvoidanceQuery::reset()
{
m_ncircles = 0;
m_nsegments = 0;
}
void dtObstacleAvoidanceQuery::addCircle(const float* pos, const float rad,
const float* vel, const float* dvel)
{
if (m_ncircles >= m_maxCircles)
return;
dtObstacleCircle* cir = &m_circles[m_ncircles++];
dtVcopy(cir->p, pos);
cir->rad = rad;
dtVcopy(cir->vel, vel);
dtVcopy(cir->dvel, dvel);
}
void dtObstacleAvoidanceQuery::addSegment(const float* p, const float* q)
{
if (m_nsegments > m_maxSegments)
return;
dtObstacleSegment* seg = &m_segments[m_nsegments++];
dtVcopy(seg->p, p);
dtVcopy(seg->q, q);
}
void dtObstacleAvoidanceQuery::prepare(const float* pos, const float* dvel)
{
// Prepare obstacles
for (int i = 0; i < m_ncircles; ++i)
{
dtObstacleCircle* cir = &m_circles[i];
// Side
const float* pa = pos;
const float* pb = cir->p;
const float orig[3] = {0,0};
float dv[3];
dtVsub(cir->dp,pb,pa);
dtVnormalize(cir->dp);
dtVsub(dv, cir->dvel, dvel);
const float a = dtTriArea2D(orig, cir->dp,dv);
if (a < 0.01f)
{
cir->np[0] = -cir->dp[2];
cir->np[2] = cir->dp[0];
}
else
{
cir->np[0] = cir->dp[2];
cir->np[2] = -cir->dp[0];
}
}
for (int i = 0; i < m_nsegments; ++i)
{
dtObstacleSegment* seg = &m_segments[i];
// Precalc if the agent is really close to the segment.
const float r = 0.01f;
float t;
seg->touch = dtDistancePtSegSqr2D(pos, seg->p, seg->q, t) < dtSqr(r);
}
}
float dtObstacleAvoidanceQuery::processSample(const float* vcand, const float cs,
const float* pos, const float rad,
const float vmax, const float* vel, const float* dvel,
dtObstacleAvoidanceDebugData* debug)
{
// Find min time of impact and exit amongst all obstacles.
float tmin = m_horizTime;
float side = 0;
int nside = 0;
for (int i = 0; i < m_ncircles; ++i)
{
const dtObstacleCircle* cir = &m_circles[i];
// RVO
float vab[3];
dtVscale(vab, vcand, 2);
dtVsub(vab, vab, vel);
dtVsub(vab, vab, cir->vel);
// Side
side += dtClamp(dtMin(dtVdot2D(cir->dp,vab)*0.5f+0.5f, dtVdot2D(cir->np,vab)*2), 0.0f, 1.0f);
nside++;
float htmin = 0, htmax = 0;
if (!sweepCircleCircle(pos,rad, vab, cir->p,cir->rad, htmin, htmax))
continue;
// Handle overlapping obstacles.
if (htmin < 0.0f && htmax > 0.0f)
{
// Avoid more when overlapped.
htmin = -htmin * 0.5f;
}
if (htmin >= 0.0f)
{
// The closest obstacle is somewhere ahead of us, keep track of nearest obstacle.
if (htmin < tmin)
tmin = htmin;
}
}
for (int i = 0; i < m_nsegments; ++i)
{
const dtObstacleSegment* seg = &m_segments[i];
float htmin = 0;
if (seg->touch)
{
// Special case when the agent is very close to the segment.
float sdir[3], snorm[3];
dtVsub(sdir, seg->q, seg->p);
snorm[0] = -sdir[2];
snorm[2] = sdir[0];
// If the velocity is pointing towards the segment, no collision.
if (dtVdot2D(snorm, vcand) < 0.0f)
continue;
// Else immediate collision.
htmin = 0.0f;
}
else
{
if (!isectRaySeg(pos, vcand, seg->p, seg->q, htmin))
continue;
}
// Avoid less when facing walls.
htmin *= 2.0f;
// The closest obstacle is somewhere ahead of us, keep track of nearest obstacle.
if (htmin < tmin)
tmin = htmin;
}
// Normalize side bias, to prevent it dominating too much.
if (nside)
side /= nside;
const float ivmax = 1.0f / vmax;
const float vpen = m_weightDesVel * (dtVdist2D(vcand, dvel) * ivmax);
const float vcpen = m_weightCurVel * (dtVdist2D(vcand, vel) * ivmax);
const float spen = m_weightSide * side;
const float tpen = m_weightToi * (1.0f/(0.1f+tmin / m_horizTime));
const float penalty = vpen + vcpen + spen + tpen;
// Store different penalties for debug viewing
if (debug)
debug->addSample(vcand, cs, penalty, vpen, vcpen, spen, tpen);
return penalty;
}
void dtObstacleAvoidanceQuery::sampleVelocityGrid(const float* pos, const float rad, const float vmax,
const float* vel, const float* dvel,
float* nvel, const int gsize,
dtObstacleAvoidanceDebugData* debug)
{
prepare(pos, dvel);
dtVset(nvel, 0,0,0);
if (debug)
debug->reset();
const float cvx = dvel[0] * m_velBias;
const float cvz = dvel[2] * m_velBias;
const float cs = vmax * 2 * (1 - m_velBias) / (float)(gsize-1);
const float half = (gsize-1)*cs*0.5f;
float minPenalty = FLT_MAX;
for (int y = 0; y < gsize; ++y)
{
for (int x = 0; x < gsize; ++x)
{
float vcand[3];
vcand[0] = cvx + x*cs - half;
vcand[1] = 0;
vcand[2] = cvz + y*cs - half;
if (dtSqr(vcand[0])+dtSqr(vcand[2]) > dtSqr(vmax+cs/2)) continue;
const float penalty = processSample(vcand, cs, pos,rad,vmax,vel,dvel, debug);
if (penalty < minPenalty)
{
minPenalty = penalty;
dtVcopy(nvel, vcand);
}
}
}
}
static const float DT_PI = 3.14159265f;
void dtObstacleAvoidanceQuery::sampleVelocityAdaptive(const float* pos, const float rad, const float vmax,
const float* vel, const float* dvel, float* nvel,
const int ndivs, const int nrings, const int depth,
dtObstacleAvoidanceDebugData* debug)
{
prepare(pos, dvel);
dtVset(nvel, 0,0,0);
if (debug)
debug->reset();
// Build sampling pattern aligned to desired velocity.
static const int MAX_PATTERN_DIVS = 32;
static const int MAX_PATTERN_RINGS = 4;
float pat[(MAX_PATTERN_DIVS*MAX_PATTERN_RINGS+1)*2];
int npat = 0;
const int nd = dtClamp(ndivs, 1, MAX_PATTERN_DIVS);
const int nr = dtClamp(nrings, 1, MAX_PATTERN_RINGS);
const float da = (1.0f/nd) * DT_PI*2;
const float dang = atan2f(dvel[2], dvel[0]);
// Always add sample at zero
pat[npat*2+0] = 0;
pat[npat*2+1] = 0;
npat++;
for (int j = 0; j < nr; ++j)
{
const float rad = (float)(nr-j)/(float)nr;
float a = dang + (j&1)*0.5f*da;
for (int i = 0; i < nd; ++i)
{
pat[npat*2+0] = cosf(a)*rad;
pat[npat*2+1] = sinf(a)*rad;
npat++;
a += da;
}
}
// Start sampling.
float cr = vmax * (1.0f-m_velBias);
float res[3];
dtVset(res, dvel[0] * m_velBias, 0, dvel[2] * m_velBias);
for (int k = 0; k < depth; ++k)
{
float minPenalty = FLT_MAX;
float bvel[3];
dtVset(bvel, 0,0,0);
for (int i = 0; i < npat; ++i)
{
float vcand[3];
vcand[0] = res[0] + pat[i*2+0]*cr;
vcand[1] = 0;
vcand[2] = res[2] + pat[i*2+1]*cr;
if (dtSqr(vcand[0])+dtSqr(vcand[2]) > dtSqr(vmax+0.001f)) continue;
const float penalty = processSample(vcand,cr/10, pos,rad,vmax,vel,dvel, debug);
if (penalty < minPenalty)
{
minPenalty = penalty;
dtVcopy(bvel, vcand);
}
}
dtVcopy(res, bvel);
cr *= 0.5f;
}
dtVcopy(nvel, res);
}

View File

@@ -1,148 +0,0 @@
//
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#ifndef DETOUROBSTACLEAVOIDANCE_H
#define DETOUROBSTACLEAVOIDANCE_H
struct dtObstacleCircle
{
float p[3]; // Position of the obstacle
float vel[3]; // Velocity of the obstacle
float dvel[3]; // Velocity of the obstacle
float rad; // Radius of the obstacle
float dp[3], np[3]; // Use for side selection during sampling.
};
struct dtObstacleSegment
{
float p[3], q[3]; // End points of the obstacle segment
bool touch;
};
static const int RVO_SAMPLE_RAD = 15;
static const int MAX_RVO_SAMPLES = (RVO_SAMPLE_RAD*2+1)*(RVO_SAMPLE_RAD*2+1) + 100;
class dtObstacleAvoidanceDebugData
{
public:
dtObstacleAvoidanceDebugData();
~dtObstacleAvoidanceDebugData();
bool init(const int maxSamples);
void reset();
void addSample(const float* vel, const float ssize, const float pen,
const float vpen, const float vcpen, const float spen, const float tpen);
void normalizeSamples();
inline int getSampleCount() const { return m_nsamples; }
inline const float* getSampleVelocity(const int i) const { return &m_vel[i*3]; }
inline float getSampleSize(const int i) const { return m_ssize[i]; }
inline float getSamplePenalty(const int i) const { return m_pen[i]; }
inline float getSampleDesiredVelocityPenalty(const int i) const { return m_vpen[i]; }
inline float getSampleCurrentVelocityPenalty(const int i) const { return m_vcpen[i]; }
inline float getSamplePreferredSidePenalty(const int i) const { return m_spen[i]; }
inline float getSampleCollisionTimePenalty(const int i) const { return m_tpen[i]; }
private:
int m_nsamples;
int m_maxSamples;
float* m_vel;
float* m_ssize;
float* m_pen;
float* m_vpen;
float* m_vcpen;
float* m_spen;
float* m_tpen;
};
dtObstacleAvoidanceDebugData* dtAllocObstacleAvoidanceDebugData();
void dtFreeObstacleAvoidanceDebugData(dtObstacleAvoidanceDebugData* ptr);
class dtObstacleAvoidanceQuery
{
public:
dtObstacleAvoidanceQuery();
~dtObstacleAvoidanceQuery();
bool init(const int maxCircles, const int maxSegments);
void reset();
void addCircle(const float* pos, const float rad,
const float* vel, const float* dvel);
void addSegment(const float* p, const float* q);
inline void setVelocitySelectionBias(float v) { m_velBias = v; }
inline void setDesiredVelocityWeight(float w) { m_weightDesVel = w; }
inline void setCurrentVelocityWeight(float w) { m_weightCurVel = w; }
inline void setPreferredSideWeight(float w) { m_weightSide = w; }
inline void setCollisionTimeWeight(float w) { m_weightToi = w; }
inline void setTimeHorizon(float t) { m_horizTime = t; }
void sampleVelocityGrid(const float* pos, const float rad, const float vmax,
const float* vel, const float* dvel, float* nvel,
const int gsize,
dtObstacleAvoidanceDebugData* debug = 0);
void sampleVelocityAdaptive(const float* pos, const float rad, const float vmax,
const float* vel, const float* dvel, float* nvel,
const int ndivs, const int nrings, const int depth,
dtObstacleAvoidanceDebugData* debug = 0);
inline int getObstacleCircleCount() const { return m_ncircles; }
const dtObstacleCircle* getObstacleCircle(const int i) { return &m_circles[i]; }
inline int getObstacleSegmentCount() const { return m_nsegments; }
const dtObstacleSegment* getObstacleSegment(const int i) { return &m_segments[i]; }
private:
void prepare(const float* pos, const float* dvel);
float processSample(const float* vcand, const float cs,
const float* pos, const float rad,
const float vmax, const float* vel, const float* dvel,
dtObstacleAvoidanceDebugData* debug);
dtObstacleCircle* insertCircle(const float dist);
dtObstacleSegment* insertSegment(const float dist);
float m_velBias;
float m_weightDesVel;
float m_weightCurVel;
float m_weightSide;
float m_weightToi;
float m_horizTime;
int m_maxCircles;
dtObstacleCircle* m_circles;
int m_ncircles;
int m_maxSegments;
dtObstacleSegment* m_segments;
int m_nsegments;
};
dtObstacleAvoidanceQuery* dtAllocObstacleAvoidanceQuery();
void dtFreeObstacleAvoidanceQuery(dtObstacleAvoidanceQuery* ptr);
#endif // DETOUROBSTACLEAVOIDANCE_H

View File

@@ -0,0 +1,59 @@
//
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#ifndef DETOURALLOCATOR_H
#define DETOURALLOCATOR_H
/// Provides hint values to the memory allocator on how long the
/// memory is expected to be used.
enum dtAllocHint
{
DT_ALLOC_PERM, ///< Memory persist after a function call.
DT_ALLOC_TEMP ///< Memory used temporarily within a function.
};
/// A memory allocation function.
// @param[in] size The size, in bytes of memory, to allocate.
// @param[in] rcAllocHint A hint to the allocator on how long the memory is expected to be in use.
// @return A pointer to the beginning of the allocated memory block, or null if the allocation failed.
/// @see dtAllocSetCustom
typedef void* (dtAllocFunc)(int size, dtAllocHint hint);
/// A memory deallocation function.
/// @param[in] ptr A pointer to a memory block previously allocated using #dtAllocFunc.
/// @see dtAllocSetCustom
typedef void (dtFreeFunc)(void* ptr);
/// Sets the base custom allocation functions to be used by Detour.
/// @param[in] allocFunc The memory allocation function to be used by #dtAlloc
/// @param[in] freeFunc The memory de-allocation function to be used by #dtFree
void dtAllocSetCustom(dtAllocFunc *allocFunc, dtFreeFunc *freeFunc);
/// Allocates a memory block.
/// @param[in] size The size, in bytes of memory, to allocate.
/// @param[in] hint A hint to the allocator on how long the memory is expected to be in use.
/// @return A pointer to the beginning of the allocated memory block, or null if the allocation failed.
/// @see dtFree
void* dtAlloc(int size, dtAllocHint hint);
/// Deallocates a memory block.
/// @param[in] ptr A pointer to a memory block previously allocated using #dtAlloc.
/// @see dtAlloc
void dtFree(void* ptr);
#endif

View File

@@ -0,0 +1,517 @@
//
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#ifndef DETOURCOMMON_H
#define DETOURCOMMON_H
#include "DetourMath.h"
/**
@defgroup detour Detour
Members in this module are used to create, manipulate, and query navigation
meshes.
@note This is a summary list of members. Use the index or search
feature to find minor members.
*/
/// @name General helper functions
/// @{
/// Used to ignore a function parameter. VS complains about unused parameters
/// and this silences the warning.
/// @param [in] _ Unused parameter
template<class T> void dtIgnoreUnused(const T&) { }
/// Swaps the values of the two parameters.
/// @param[in,out] a Value A
/// @param[in,out] b Value B
template<class T> inline void dtSwap(T& a, T& b) { T t = a; a = b; b = t; }
/// Returns the minimum of two values.
/// @param[in] a Value A
/// @param[in] b Value B
/// @return The minimum of the two values.
template<class T> inline T dtMin(T a, T b) { return a < b ? a : b; }
/// Returns the maximum of two values.
/// @param[in] a Value A
/// @param[in] b Value B
/// @return The maximum of the two values.
template<class T> inline T dtMax(T a, T b) { return a > b ? a : b; }
/// Returns the absolute value.
/// @param[in] a The value.
/// @return The absolute value of the specified value.
template<class T> inline T dtAbs(T a) { return a < 0 ? -a : a; }
/// Returns the square of the value.
/// @param[in] a The value.
/// @return The square of the value.
template<class T> inline T dtSqr(T a) { return a*a; }
/// Clamps the value to the specified range.
/// @param[in] v The value to clamp.
/// @param[in] mn The minimum permitted return value.
/// @param[in] mx The maximum permitted return value.
/// @return The value, clamped to the specified range.
template<class T> inline T dtClamp(T v, T mn, T mx) { return v < mn ? mn : (v > mx ? mx : v); }
/// @}
/// @name Vector helper functions.
/// @{
/// Derives the cross product of two vectors. (@p v1 x @p v2)
/// @param[out] dest The cross product. [(x, y, z)]
/// @param[in] v1 A Vector [(x, y, z)]
/// @param[in] v2 A vector [(x, y, z)]
inline void dtVcross(float* dest, const float* v1, const float* v2)
{
dest[0] = v1[1]*v2[2] - v1[2]*v2[1];
dest[1] = v1[2]*v2[0] - v1[0]*v2[2];
dest[2] = v1[0]*v2[1] - v1[1]*v2[0];
}
/// Derives the dot product of two vectors. (@p v1 . @p v2)
/// @param[in] v1 A Vector [(x, y, z)]
/// @param[in] v2 A vector [(x, y, z)]
/// @return The dot product.
inline float dtVdot(const float* v1, const float* v2)
{
return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
}
/// Performs a scaled vector addition. (@p v1 + (@p v2 * @p s))
/// @param[out] dest The result vector. [(x, y, z)]
/// @param[in] v1 The base vector. [(x, y, z)]
/// @param[in] v2 The vector to scale and add to @p v1. [(x, y, z)]
/// @param[in] s The amount to scale @p v2 by before adding to @p v1.
inline void dtVmad(float* dest, const float* v1, const float* v2, const float s)
{
dest[0] = v1[0]+v2[0]*s;
dest[1] = v1[1]+v2[1]*s;
dest[2] = v1[2]+v2[2]*s;
}
/// Performs a linear interpolation between two vectors. (@p v1 toward @p v2)
/// @param[out] dest The result vector. [(x, y, x)]
/// @param[in] v1 The starting vector.
/// @param[in] v2 The destination vector.
/// @param[in] t The interpolation factor. [Limits: 0 <= value <= 1.0]
inline void dtVlerp(float* dest, const float* v1, const float* v2, const float t)
{
dest[0] = v1[0]+(v2[0]-v1[0])*t;
dest[1] = v1[1]+(v2[1]-v1[1])*t;
dest[2] = v1[2]+(v2[2]-v1[2])*t;
}
/// Performs a vector addition. (@p v1 + @p v2)
/// @param[out] dest The result vector. [(x, y, z)]
/// @param[in] v1 The base vector. [(x, y, z)]
/// @param[in] v2 The vector to add to @p v1. [(x, y, z)]
inline void dtVadd(float* dest, const float* v1, const float* v2)
{
dest[0] = v1[0]+v2[0];
dest[1] = v1[1]+v2[1];
dest[2] = v1[2]+v2[2];
}
/// Performs a vector subtraction. (@p v1 - @p v2)
/// @param[out] dest The result vector. [(x, y, z)]
/// @param[in] v1 The base vector. [(x, y, z)]
/// @param[in] v2 The vector to subtract from @p v1. [(x, y, z)]
inline void dtVsub(float* dest, const float* v1, const float* v2)
{
dest[0] = v1[0]-v2[0];
dest[1] = v1[1]-v2[1];
dest[2] = v1[2]-v2[2];
}
/// Scales the vector by the specified value. (@p v * @p t)
/// @param[out] dest The result vector. [(x, y, z)]
/// @param[in] v The vector to scale. [(x, y, z)]
/// @param[in] t The scaling factor.
inline void dtVscale(float* dest, const float* v, const float t)
{
dest[0] = v[0]*t;
dest[1] = v[1]*t;
dest[2] = v[2]*t;
}
/// Selects the minimum value of each element from the specified vectors.
/// @param[in,out] mn A vector. (Will be updated with the result.) [(x, y, z)]
/// @param[in] v A vector. [(x, y, z)]
inline void dtVmin(float* mn, const float* v)
{
mn[0] = dtMin(mn[0], v[0]);
mn[1] = dtMin(mn[1], v[1]);
mn[2] = dtMin(mn[2], v[2]);
}
/// Selects the maximum value of each element from the specified vectors.
/// @param[in,out] mx A vector. (Will be updated with the result.) [(x, y, z)]
/// @param[in] v A vector. [(x, y, z)]
inline void dtVmax(float* mx, const float* v)
{
mx[0] = dtMax(mx[0], v[0]);
mx[1] = dtMax(mx[1], v[1]);
mx[2] = dtMax(mx[2], v[2]);
}
/// Sets the vector elements to the specified values.
/// @param[out] dest The result vector. [(x, y, z)]
/// @param[in] x The x-value of the vector.
/// @param[in] y The y-value of the vector.
/// @param[in] z The z-value of the vector.
inline void dtVset(float* dest, const float x, const float y, const float z)
{
dest[0] = x; dest[1] = y; dest[2] = z;
}
/// Performs a vector copy.
/// @param[out] dest The result. [(x, y, z)]
/// @param[in] a The vector to copy. [(x, y, z)]
inline void dtVcopy(float* dest, const float* a)
{
dest[0] = a[0];
dest[1] = a[1];
dest[2] = a[2];
}
/// Derives the scalar length of the vector.
/// @param[in] v The vector. [(x, y, z)]
/// @return The scalar length of the vector.
inline float dtVlen(const float* v)
{
return dtMathSqrtf(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
}
/// Derives the square of the scalar length of the vector. (len * len)
/// @param[in] v The vector. [(x, y, z)]
/// @return The square of the scalar length of the vector.
inline float dtVlenSqr(const float* v)
{
return v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
}
/// Returns the distance between two points.
/// @param[in] v1 A point. [(x, y, z)]
/// @param[in] v2 A point. [(x, y, z)]
/// @return The distance between the two points.
inline float dtVdist(const float* v1, const float* v2)
{
const float dx = v2[0] - v1[0];
const float dy = v2[1] - v1[1];
const float dz = v2[2] - v1[2];
return dtMathSqrtf(dx*dx + dy*dy + dz*dz);
}
/// Returns the square of the distance between two points.
/// @param[in] v1 A point. [(x, y, z)]
/// @param[in] v2 A point. [(x, y, z)]
/// @return The square of the distance between the two points.
inline float dtVdistSqr(const float* v1, const float* v2)
{
const float dx = v2[0] - v1[0];
const float dy = v2[1] - v1[1];
const float dz = v2[2] - v1[2];
return dx*dx + dy*dy + dz*dz;
}
/// Derives the distance between the specified points on the xz-plane.
/// @param[in] v1 A point. [(x, y, z)]
/// @param[in] v2 A point. [(x, y, z)]
/// @return The distance between the point on the xz-plane.
///
/// The vectors are projected onto the xz-plane, so the y-values are ignored.
inline float dtVdist2D(const float* v1, const float* v2)
{
const float dx = v2[0] - v1[0];
const float dz = v2[2] - v1[2];
return dtMathSqrtf(dx*dx + dz*dz);
}
/// Derives the square of the distance between the specified points on the xz-plane.
/// @param[in] v1 A point. [(x, y, z)]
/// @param[in] v2 A point. [(x, y, z)]
/// @return The square of the distance between the point on the xz-plane.
inline float dtVdist2DSqr(const float* v1, const float* v2)
{
const float dx = v2[0] - v1[0];
const float dz = v2[2] - v1[2];
return dx*dx + dz*dz;
}
/// Normalizes the vector.
/// @param[in,out] v The vector to normalize. [(x, y, z)]
inline void dtVnormalize(float* v)
{
float d = 1.0f / dtMathSqrtf(dtSqr(v[0]) + dtSqr(v[1]) + dtSqr(v[2]));
v[0] *= d;
v[1] *= d;
v[2] *= d;
}
/// Performs a 'sloppy' colocation check of the specified points.
/// @param[in] p0 A point. [(x, y, z)]
/// @param[in] p1 A point. [(x, y, z)]
/// @return True if the points are considered to be at the same location.
///
/// Basically, this function will return true if the specified points are
/// close enough to eachother to be considered colocated.
inline bool dtVequal(const float* p0, const float* p1)
{
static const float thr = dtSqr(1.0f/16384.0f);
const float d = dtVdistSqr(p0, p1);
return d < thr;
}
/// Derives the dot product of two vectors on the xz-plane. (@p u . @p v)
/// @param[in] u A vector [(x, y, z)]
/// @param[in] v A vector [(x, y, z)]
/// @return The dot product on the xz-plane.
///
/// The vectors are projected onto the xz-plane, so the y-values are ignored.
inline float dtVdot2D(const float* u, const float* v)
{
return u[0]*v[0] + u[2]*v[2];
}
/// Derives the xz-plane 2D perp product of the two vectors. (uz*vx - ux*vz)
/// @param[in] u The LHV vector [(x, y, z)]
/// @param[in] v The RHV vector [(x, y, z)]
/// @return The dot product on the xz-plane.
///
/// The vectors are projected onto the xz-plane, so the y-values are ignored.
inline float dtVperp2D(const float* u, const float* v)
{
return u[2]*v[0] - u[0]*v[2];
}
/// @}
/// @name Computational geometry helper functions.
/// @{
/// Derives the signed xz-plane area of the triangle ABC, or the relationship of line AB to point C.
/// @param[in] a Vertex A. [(x, y, z)]
/// @param[in] b Vertex B. [(x, y, z)]
/// @param[in] c Vertex C. [(x, y, z)]
/// @return The signed xz-plane area of the triangle.
inline float dtTriArea2D(const float* a, const float* b, const float* c)
{
const float abx = b[0] - a[0];
const float abz = b[2] - a[2];
const float acx = c[0] - a[0];
const float acz = c[2] - a[2];
return acx*abz - abx*acz;
}
/// Determines if two axis-aligned bounding boxes overlap.
/// @param[in] amin Minimum bounds of box A. [(x, y, z)]
/// @param[in] amax Maximum bounds of box A. [(x, y, z)]
/// @param[in] bmin Minimum bounds of box B. [(x, y, z)]
/// @param[in] bmax Maximum bounds of box B. [(x, y, z)]
/// @return True if the two AABB's overlap.
/// @see dtOverlapBounds
inline bool dtOverlapQuantBounds(const unsigned short amin[3], const unsigned short amax[3],
const unsigned short bmin[3], const unsigned short bmax[3])
{
bool overlap = true;
overlap = (amin[0] > bmax[0] || amax[0] < bmin[0]) ? false : overlap;
overlap = (amin[1] > bmax[1] || amax[1] < bmin[1]) ? false : overlap;
overlap = (amin[2] > bmax[2] || amax[2] < bmin[2]) ? false : overlap;
return overlap;
}
/// Determines if two axis-aligned bounding boxes overlap.
/// @param[in] amin Minimum bounds of box A. [(x, y, z)]
/// @param[in] amax Maximum bounds of box A. [(x, y, z)]
/// @param[in] bmin Minimum bounds of box B. [(x, y, z)]
/// @param[in] bmax Maximum bounds of box B. [(x, y, z)]
/// @return True if the two AABB's overlap.
/// @see dtOverlapQuantBounds
inline bool dtOverlapBounds(const float* amin, const float* amax,
const float* bmin, const float* bmax)
{
bool overlap = true;
overlap = (amin[0] > bmax[0] || amax[0] < bmin[0]) ? false : overlap;
overlap = (amin[1] > bmax[1] || amax[1] < bmin[1]) ? false : overlap;
overlap = (amin[2] > bmax[2] || amax[2] < bmin[2]) ? false : overlap;
return overlap;
}
/// Derives the closest point on a triangle from the specified reference point.
/// @param[out] closest The closest point on the triangle.
/// @param[in] p The reference point from which to test. [(x, y, z)]
/// @param[in] a Vertex A of triangle ABC. [(x, y, z)]
/// @param[in] b Vertex B of triangle ABC. [(x, y, z)]
/// @param[in] c Vertex C of triangle ABC. [(x, y, z)]
void dtClosestPtPointTriangle(float* closest, const float* p,
const float* a, const float* b, const float* c);
/// Derives the y-axis height of the closest point on the triangle from the specified reference point.
/// @param[in] p The reference point from which to test. [(x, y, z)]
/// @param[in] a Vertex A of triangle ABC. [(x, y, z)]
/// @param[in] b Vertex B of triangle ABC. [(x, y, z)]
/// @param[in] c Vertex C of triangle ABC. [(x, y, z)]
/// @param[out] h The resulting height.
bool dtClosestHeightPointTriangle(const float* p, const float* a, const float* b, const float* c, float& h);
bool dtIntersectSegmentPoly2D(const float* p0, const float* p1,
const float* verts, int nverts,
float& tmin, float& tmax,
int& segMin, int& segMax);
bool dtIntersectSegSeg2D(const float* ap, const float* aq,
const float* bp, const float* bq,
float& s, float& t);
/// Determines if the specified point is inside the convex polygon on the xz-plane.
/// @param[in] pt The point to check. [(x, y, z)]
/// @param[in] verts The polygon vertices. [(x, y, z) * @p nverts]
/// @param[in] nverts The number of vertices. [Limit: >= 3]
/// @return True if the point is inside the polygon.
bool dtPointInPolygon(const float* pt, const float* verts, const int nverts);
bool dtDistancePtPolyEdgesSqr(const float* pt, const float* verts, const int nverts,
float* ed, float* et);
float dtDistancePtSegSqr2D(const float* pt, const float* p, const float* q, float& t);
/// Derives the centroid of a convex polygon.
/// @param[out] tc The centroid of the polgyon. [(x, y, z)]
/// @param[in] idx The polygon indices. [(vertIndex) * @p nidx]
/// @param[in] nidx The number of indices in the polygon. [Limit: >= 3]
/// @param[in] verts The polygon vertices. [(x, y, z) * vertCount]
void dtCalcPolyCenter(float* tc, const unsigned short* idx, int nidx, const float* verts);
/// Determines if the two convex polygons overlap on the xz-plane.
/// @param[in] polya Polygon A vertices. [(x, y, z) * @p npolya]
/// @param[in] npolya The number of vertices in polygon A.
/// @param[in] polyb Polygon B vertices. [(x, y, z) * @p npolyb]
/// @param[in] npolyb The number of vertices in polygon B.
/// @return True if the two polygons overlap.
bool dtOverlapPolyPoly2D(const float* polya, const int npolya,
const float* polyb, const int npolyb);
/// @}
/// @name Miscellanious functions.
/// @{
inline unsigned int dtNextPow2(unsigned int v)
{
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v++;
return v;
}
inline unsigned int dtIlog2(unsigned int v)
{
unsigned int r;
unsigned int shift;
r = (v > 0xffff) << 4; v >>= r;
shift = (v > 0xff) << 3; v >>= shift; r |= shift;
shift = (v > 0xf) << 2; v >>= shift; r |= shift;
shift = (v > 0x3) << 1; v >>= shift; r |= shift;
r |= (v >> 1);
return r;
}
inline int dtAlign4(int x) { return (x+3) & ~3; }
inline int dtOppositeTile(int side) { return (side+4) & 0x7; }
inline void dtSwapByte(unsigned char* a, unsigned char* b)
{
unsigned char tmp = *a;
*a = *b;
*b = tmp;
}
inline void dtSwapEndian(unsigned short* v)
{
unsigned char* x = (unsigned char*)v;
dtSwapByte(x+0, x+1);
}
inline void dtSwapEndian(short* v)
{
unsigned char* x = (unsigned char*)v;
dtSwapByte(x+0, x+1);
}
inline void dtSwapEndian(unsigned int* v)
{
unsigned char* x = (unsigned char*)v;
dtSwapByte(x+0, x+3); dtSwapByte(x+1, x+2);
}
inline void dtSwapEndian(int* v)
{
unsigned char* x = (unsigned char*)v;
dtSwapByte(x+0, x+3); dtSwapByte(x+1, x+2);
}
inline void dtSwapEndian(float* v)
{
unsigned char* x = (unsigned char*)v;
dtSwapByte(x+0, x+3); dtSwapByte(x+1, x+2);
}
void dtRandomPointInConvexPoly(const float* pts, const int npts, float* areas,
const float s, const float t, float* out);
/// @}
#endif // DETOURCOMMON_H
///////////////////////////////////////////////////////////////////////////
// This section contains detailed documentation for members that don't have
// a source file. It reduces clutter in the main section of the header.
/**
@fn float dtTriArea2D(const float* a, const float* b, const float* c)
@par
The vertices are projected onto the xz-plane, so the y-values are ignored.
This is a low cost function than can be used for various purposes. Its main purpose
is for point/line relationship testing.
In all cases: A value of zero indicates that all vertices are collinear or represent the same point.
(On the xz-plane.)
When used for point/line relationship tests, AB usually represents a line against which
the C point is to be tested. In this case:
A positive value indicates that point C is to the left of line AB, looking from A toward B.<br/>
A negative value indicates that point C is to the right of lineAB, looking from A toward B.
When used for evaluating a triangle:
The absolute value of the return value is two times the area of the triangle when it is
projected onto the xz-plane.
A positive return value indicates:
<ul>
<li>The vertices are wrapped in the normal Detour wrap direction.</li>
<li>The triangle's 3D face normal is in the general up direction.</li>
</ul>
A negative return value indicates:
<ul>
<li>The vertices are reverse wrapped. (Wrapped opposite the normal Detour wrap direction.)</li>
<li>The triangle's 3D face normal is in the general down direction.</li>
</ul>
*/

View File

@@ -0,0 +1,19 @@
/**
@defgroup detour Detour
Members in this module are wrappers around the standard math library
*/
#ifndef DETOURMATH_H
#define DETOURMATH_H
#include <math.h>
inline float dtMathFabsf(float x) { return fabsf(x); }
inline float dtMathSqrtf(float x) { return sqrtf(x); }
inline float dtMathFloorf(float x) { return floorf(x); }
inline float dtMathCeilf(float x) { return ceilf(x); }
inline float dtMathCosf(float x) { return cosf(x); }
inline float dtMathSinf(float x) { return sinf(x); }
inline float dtMathAtan2f(float y, float x) { return atan2f(y, x); }
#endif

View File

@@ -0,0 +1,708 @@
//
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#ifndef DETOURNAVMESH_H
#define DETOURNAVMESH_H
#include "DetourAlloc.h"
#include "DetourStatus.h"
// Edited by TC
#if defined(WIN32) && !defined(__MINGW32__)
/// Do not rename back to uint64. Otherwise mac complains about typedef redefinition
typedef unsigned __int64 uint64_d;
#else
#include <stdint.h>
#ifndef uint64_t
#ifdef __linux__
#include <linux/types.h>
#endif
#endif
/// Do not rename back to uint64. Otherwise mac complains about typedef redefinition
typedef uint64_t uint64_d;
#endif
// Note: If you want to use 64-bit refs, change the types of both dtPolyRef & dtTileRef.
// It is also recommended that you change dtHashRef() to a proper 64-bit hash.
// Edited by TC
// We cannot have over 31 bits for either tile nor poly
// without changing polyCount to use 64bits too.
/// A handle to a polygon within a navigation mesh tile.
/// @ingroup detour
typedef uint64_d dtPolyRef; // Edited by TC
/// A handle to a tile within a navigation mesh.
/// @ingroup detour
typedef uint64_d dtTileRef; // Edited by TC
/// The maximum number of vertices per navigation polygon.
/// @ingroup detour
static const int DT_VERTS_PER_POLYGON = 6;
/// @{
/// @name Tile Serialization Constants
/// These constants are used to detect whether a navigation tile's data
/// and state format is compatible with the current build.
///
/// A magic number used to detect compatibility of navigation tile data.
static const int DT_NAVMESH_MAGIC = 'D'<<24 | 'N'<<16 | 'A'<<8 | 'V';
/// A version number used to detect compatibility of navigation tile data.
static const int DT_NAVMESH_VERSION = 7;
/// A magic number used to detect the compatibility of navigation tile states.
static const int DT_NAVMESH_STATE_MAGIC = 'D'<<24 | 'N'<<16 | 'M'<<8 | 'S';
/// A version number used to detect compatibility of navigation tile states.
static const int DT_NAVMESH_STATE_VERSION = 1;
/// @}
/// A flag that indicates that an entity links to an external entity.
/// (E.g. A polygon edge is a portal that links to another polygon.)
static const unsigned short DT_EXT_LINK = 0x8000;
/// A value that indicates the entity does not link to anything.
static const unsigned int DT_NULL_LINK = 0xffffffff;
/// A flag that indicates that an off-mesh connection can be traversed in both directions. (Is bidirectional.)
static const unsigned int DT_OFFMESH_CON_BIDIR = 1;
/// The maximum number of user defined area ids.
/// @ingroup detour
static const int DT_MAX_AREAS = 64;
static const int STATIC_SALT_BITS = 12;
static const int STATIC_TILE_BITS = 21;
static const int STATIC_POLY_BITS = 31;
// we cannot have over 31 bits for either tile nor poly
// without changing polyCount to use 64bits too.
/// Tile flags used for various functions and fields.
/// For an example, see dtNavMesh::addTile().
enum dtTileFlags
{
/// The navigation mesh owns the tile memory and is responsible for freeing it.
DT_TILE_FREE_DATA = 0x01,
};
/// Vertex flags returned by dtNavMeshQuery::findStraightPath.
enum dtStraightPathFlags
{
DT_STRAIGHTPATH_START = 0x01, ///< The vertex is the start position in the path.
DT_STRAIGHTPATH_END = 0x02, ///< The vertex is the end position in the path.
DT_STRAIGHTPATH_OFFMESH_CONNECTION = 0x04, ///< The vertex is the start of an off-mesh connection.
};
/// Options for dtNavMeshQuery::findStraightPath.
enum dtStraightPathOptions
{
DT_STRAIGHTPATH_AREA_CROSSINGS = 0x01, ///< Add a vertex at every polygon edge crossing where area changes.
DT_STRAIGHTPATH_ALL_CROSSINGS = 0x02, ///< Add a vertex at every polygon edge crossing.
};
/// Options for dtNavMeshQuery::findPath
enum dtFindPathOptions
{
DT_FINDPATH_LOW_QUALITY_FAR = 0x01, ///< [provisional] trade quality for performance far from the origin. The idea is that by then a new query will be issued
DT_FINDPATH_ANY_ANGLE = 0x02, ///< use raycasts during pathfind to "shortcut" (raycast still consider costs)
};
/// Options for dtNavMeshQuery::raycast
enum dtRaycastOptions
{
DT_RAYCAST_USE_COSTS = 0x01, ///< Raycast should calculate movement cost along the ray and fill RaycastHit::cost
};
/// Limit raycasting during any angle pahfinding
/// The limit is given as a multiple of the character radius
static const float DT_RAY_CAST_LIMIT_PROPORTIONS = 50.0f;
/// Flags representing the type of a navigation mesh polygon.
enum dtPolyTypes
{
/// The polygon is a standard convex polygon that is part of the surface of the mesh.
DT_POLYTYPE_GROUND = 0,
/// The polygon is an off-mesh connection consisting of two vertices.
DT_POLYTYPE_OFFMESH_CONNECTION = 1,
};
/// Defines a polyogn within a dtMeshTile object.
/// @ingroup detour
struct dtPoly
{
/// Index to first link in linked list. (Or #DT_NULL_LINK if there is no link.)
unsigned int firstLink;
/// The indices of the polygon's vertices.
/// The actual vertices are located in dtMeshTile::verts.
unsigned short verts[DT_VERTS_PER_POLYGON];
/// Packed data representing neighbor polygons references and flags for each edge.
unsigned short neis[DT_VERTS_PER_POLYGON];
/// The user defined polygon flags.
unsigned short flags;
/// The number of vertices in the polygon.
unsigned char vertCount;
/// The bit packed area id and polygon type.
/// @note Use the structure's set and get methods to acess this value.
unsigned char areaAndtype;
/// Sets the user defined area id. [Limit: < #DT_MAX_AREAS]
inline void setArea(unsigned char a) { areaAndtype = (areaAndtype & 0xc0) | (a & 0x3f); }
/// Sets the polygon type. (See: #dtPolyTypes.)
inline void setType(unsigned char t) { areaAndtype = (areaAndtype & 0x3f) | (t << 6); }
/// Gets the user defined area id.
inline unsigned char getArea() const { return areaAndtype & 0x3f; }
/// Gets the polygon type. (See: #dtPolyTypes)
inline unsigned char getType() const { return areaAndtype >> 6; }
};
/// Defines the location of detail sub-mesh data within a dtMeshTile.
struct dtPolyDetail
{
unsigned int vertBase; ///< The offset of the vertices in the dtMeshTile::detailVerts array.
unsigned int triBase; ///< The offset of the triangles in the dtMeshTile::detailTris array.
unsigned char vertCount; ///< The number of vertices in the sub-mesh.
unsigned char triCount; ///< The number of triangles in the sub-mesh.
};
/// Defines a link between polygons.
/// @note This structure is rarely if ever used by the end user.
/// @see dtMeshTile
struct dtLink
{
dtPolyRef ref; ///< Neighbour reference. (The neighbor that is linked to.)
unsigned int next; ///< Index of the next link.
unsigned char edge; ///< Index of the polygon edge that owns this link.
unsigned char side; ///< If a boundary link, defines on which side the link is.
unsigned char bmin; ///< If a boundary link, defines the minimum sub-edge area.
unsigned char bmax; ///< If a boundary link, defines the maximum sub-edge area.
};
/// Bounding volume node.
/// @note This structure is rarely if ever used by the end user.
/// @see dtMeshTile
struct dtBVNode
{
unsigned short bmin[3]; ///< Minimum bounds of the node's AABB. [(x, y, z)]
unsigned short bmax[3]; ///< Maximum bounds of the node's AABB. [(x, y, z)]
int i; ///< The node's index. (Negative for escape sequence.)
};
/// Defines an navigation mesh off-mesh connection within a dtMeshTile object.
/// An off-mesh connection is a user defined traversable connection made up to two vertices.
struct dtOffMeshConnection
{
/// The endpoints of the connection. [(ax, ay, az, bx, by, bz)]
float pos[6];
/// The radius of the endpoints. [Limit: >= 0]
float rad;
/// The polygon reference of the connection within the tile.
unsigned short poly;
/// Link flags.
/// @note These are not the connection's user defined flags. Those are assigned via the
/// connection's dtPoly definition. These are link flags used for internal purposes.
unsigned char flags;
/// End point side.
unsigned char side;
/// The id of the offmesh connection. (User assigned when the navigation mesh is built.)
unsigned int userId;
};
/// Provides high level information related to a dtMeshTile object.
/// @ingroup detour
struct dtMeshHeader
{
int magic; ///< Tile magic number. (Used to identify the data format.)
int version; ///< Tile data format version number.
int x; ///< The x-position of the tile within the dtNavMesh tile grid. (x, y, layer)
int y; ///< The y-position of the tile within the dtNavMesh tile grid. (x, y, layer)
int layer; ///< The layer of the tile within the dtNavMesh tile grid. (x, y, layer)
unsigned int userId; ///< The user defined id of the tile.
int polyCount; ///< The number of polygons in the tile.
int vertCount; ///< The number of vertices in the tile.
int maxLinkCount; ///< The number of allocated links.
int detailMeshCount; ///< The number of sub-meshes in the detail mesh.
/// The number of unique vertices in the detail mesh. (In addition to the polygon vertices.)
int detailVertCount;
int detailTriCount; ///< The number of triangles in the detail mesh.
int bvNodeCount; ///< The number of bounding volume nodes. (Zero if bounding volumes are disabled.)
int offMeshConCount; ///< The number of off-mesh connections.
int offMeshBase; ///< The index of the first polygon which is an off-mesh connection.
float walkableHeight; ///< The height of the agents using the tile.
float walkableRadius; ///< The radius of the agents using the tile.
float walkableClimb; ///< The maximum climb height of the agents using the tile.
float bmin[3]; ///< The minimum bounds of the tile's AABB. [(x, y, z)]
float bmax[3]; ///< The maximum bounds of the tile's AABB. [(x, y, z)]
/// The bounding volume quantization factor.
float bvQuantFactor;
};
/// Defines a navigation mesh tile.
/// @ingroup detour
struct dtMeshTile
{
unsigned int salt; ///< Counter describing modifications to the tile.
unsigned int linksFreeList; ///< Index to the next free link.
dtMeshHeader* header; ///< The tile header.
dtPoly* polys; ///< The tile polygons. [Size: dtMeshHeader::polyCount]
float* verts; ///< The tile vertices. [Size: dtMeshHeader::vertCount]
dtLink* links; ///< The tile links. [Size: dtMeshHeader::maxLinkCount]
dtPolyDetail* detailMeshes; ///< The tile's detail sub-meshes. [Size: dtMeshHeader::detailMeshCount]
/// The detail mesh's unique vertices. [(x, y, z) * dtMeshHeader::detailVertCount]
float* detailVerts;
/// The detail mesh's triangles. [(vertA, vertB, vertC) * dtMeshHeader::detailTriCount]
unsigned char* detailTris;
/// The tile bounding volume nodes. [Size: dtMeshHeader::bvNodeCount]
/// (Will be null if bounding volumes are disabled.)
dtBVNode* bvTree;
dtOffMeshConnection* offMeshCons; ///< The tile off-mesh connections. [Size: dtMeshHeader::offMeshConCount]
unsigned char* data; ///< The tile data. (Not directly accessed under normal situations.)
int dataSize; ///< Size of the tile data.
int flags; ///< Tile flags. (See: #dtTileFlags)
dtMeshTile* next; ///< The next free tile, or the next tile in the spatial grid.
};
/// Configuration parameters used to define multi-tile navigation meshes.
/// The values are used to allocate space during the initialization of a navigation mesh.
/// @see dtNavMesh::init()
/// @ingroup detour
struct dtNavMeshParams
{
float orig[3]; ///< The world space origin of the navigation mesh's tile space. [(x, y, z)]
float tileWidth; ///< The width of each tile. (Along the x-axis.)
float tileHeight; ///< The height of each tile. (Along the z-axis.)
int maxTiles; ///< The maximum number of tiles the navigation mesh can contain.
int maxPolys; ///< The maximum number of polygons each tile can contain.
};
/// A navigation mesh based on tiles of convex polygons.
/// @ingroup detour
class dtNavMesh
{
public:
dtNavMesh();
~dtNavMesh();
/// @{
/// @name Initialization and Tile Management
/// Initializes the navigation mesh for tiled use.
/// @param[in] params Initialization parameters.
/// @return The status flags for the operation.
dtStatus init(const dtNavMeshParams* params);
/// Initializes the navigation mesh for single tile use.
/// @param[in] data Data of the new tile. (See: #dtCreateNavMeshData)
/// @param[in] dataSize The data size of the new tile.
/// @param[in] flags The tile flags. (See: #dtTileFlags)
/// @return The status flags for the operation.
/// @see dtCreateNavMeshData
dtStatus init(unsigned char* data, const int dataSize, const int flags);
/// The navigation mesh initialization params.
const dtNavMeshParams* getParams() const;
/// Adds a tile to the navigation mesh.
/// @param[in] data Data for the new tile mesh. (See: #dtCreateNavMeshData)
/// @param[in] dataSize Data size of the new tile mesh.
/// @param[in] flags Tile flags. (See: #dtTileFlags)
/// @param[in] lastRef The desired reference for the tile. (When reloading a tile.) [opt] [Default: 0]
/// @param[out] result The tile reference. (If the tile was succesfully added.) [opt]
/// @return The status flags for the operation.
dtStatus addTile(unsigned char* data, int dataSize, int flags, dtTileRef lastRef, dtTileRef* result);
/// Removes the specified tile from the navigation mesh.
/// @param[in] ref The reference of the tile to remove.
/// @param[out] data Data associated with deleted tile.
/// @param[out] dataSize Size of the data associated with deleted tile.
/// @return The status flags for the operation.
dtStatus removeTile(dtTileRef ref, unsigned char** data, int* dataSize);
/// @}
/// @{
/// @name Query Functions
/// Calculates the tile grid location for the specified world position.
/// @param[in] pos The world position for the query. [(x, y, z)]
/// @param[out] tx The tile's x-location. (x, y)
/// @param[out] ty The tile's y-location. (x, y)
void calcTileLoc(const float* pos, int* tx, int* ty) const;
/// Gets the tile at the specified grid location.
/// @param[in] x The tile's x-location. (x, y, layer)
/// @param[in] y The tile's y-location. (x, y, layer)
/// @param[in] layer The tile's layer. (x, y, layer)
/// @return The tile, or null if the tile does not exist.
const dtMeshTile* getTileAt(const int x, const int y, const int layer) const;
/// Gets all tiles at the specified grid location. (All layers.)
/// @param[in] x The tile's x-location. (x, y)
/// @param[in] y The tile's y-location. (x, y)
/// @param[out] tiles A pointer to an array of tiles that will hold the result.
/// @param[in] maxTiles The maximum tiles the tiles parameter can hold.
/// @return The number of tiles returned in the tiles array.
int getTilesAt(const int x, const int y,
dtMeshTile const** tiles, const int maxTiles) const;
/// Gets the tile reference for the tile at specified grid location.
/// @param[in] x The tile's x-location. (x, y, layer)
/// @param[in] y The tile's y-location. (x, y, layer)
/// @param[in] layer The tile's layer. (x, y, layer)
/// @return The tile reference of the tile, or 0 if there is none.
dtTileRef getTileRefAt(int x, int y, int layer) const;
/// Gets the tile reference for the specified tile.
/// @param[in] tile The tile.
/// @return The tile reference of the tile.
dtTileRef getTileRef(const dtMeshTile* tile) const;
/// Gets the tile for the specified tile reference.
/// @param[in] ref The tile reference of the tile to retrieve.
/// @return The tile for the specified reference, or null if the
/// reference is invalid.
const dtMeshTile* getTileByRef(dtTileRef ref) const;
/// The maximum number of tiles supported by the navigation mesh.
/// @return The maximum number of tiles supported by the navigation mesh.
int getMaxTiles() const;
/// Gets the tile at the specified index.
/// @param[in] i The tile index. [Limit: 0 >= index < #getMaxTiles()]
/// @return The tile at the specified index.
const dtMeshTile* getTile(int i) const;
/// Gets the tile and polygon for the specified polygon reference.
/// @param[in] ref The reference for the a polygon.
/// @param[out] tile The tile containing the polygon.
/// @param[out] poly The polygon.
/// @return The status flags for the operation.
dtStatus getTileAndPolyByRef(const dtPolyRef ref, const dtMeshTile** tile, const dtPoly** poly) const;
/// Returns the tile and polygon for the specified polygon reference.
/// @param[in] ref A known valid reference for a polygon.
/// @param[out] tile The tile containing the polygon.
/// @param[out] poly The polygon.
void getTileAndPolyByRefUnsafe(const dtPolyRef ref, const dtMeshTile** tile, const dtPoly** poly) const;
/// Checks the validity of a polygon reference.
/// @param[in] ref The polygon reference to check.
/// @return True if polygon reference is valid for the navigation mesh.
bool isValidPolyRef(dtPolyRef ref) const;
/// Gets the polygon reference for the tile's base polygon.
/// @param[in] tile The tile.
/// @return The polygon reference for the base polygon in the specified tile.
dtPolyRef getPolyRefBase(const dtMeshTile* tile) const;
/// Gets the endpoints for an off-mesh connection, ordered by "direction of travel".
/// @param[in] prevRef The reference of the polygon before the connection.
/// @param[in] polyRef The reference of the off-mesh connection polygon.
/// @param[out] startPos The start position of the off-mesh connection. [(x, y, z)]
/// @param[out] endPos The end position of the off-mesh connection. [(x, y, z)]
/// @return The status flags for the operation.
dtStatus getOffMeshConnectionPolyEndPoints(dtPolyRef prevRef, dtPolyRef polyRef, float* startPos, float* endPos) const;
/// Gets the specified off-mesh connection.
/// @param[in] ref The polygon reference of the off-mesh connection.
/// @return The specified off-mesh connection, or null if the polygon reference is not valid.
const dtOffMeshConnection* getOffMeshConnectionByRef(dtPolyRef ref) const;
/// @}
/// @{
/// @name State Management
/// These functions do not effect #dtTileRef or #dtPolyRef's.
/// Sets the user defined flags for the specified polygon.
/// @param[in] ref The polygon reference.
/// @param[in] flags The new flags for the polygon.
/// @return The status flags for the operation.
dtStatus setPolyFlags(dtPolyRef ref, unsigned short flags);
/// Gets the user defined flags for the specified polygon.
/// @param[in] ref The polygon reference.
/// @param[out] resultFlags The polygon flags.
/// @return The status flags for the operation.
dtStatus getPolyFlags(dtPolyRef ref, unsigned short* resultFlags) const;
/// Sets the user defined area for the specified polygon.
/// @param[in] ref The polygon reference.
/// @param[in] area The new area id for the polygon. [Limit: < #DT_MAX_AREAS]
/// @return The status flags for the operation.
dtStatus setPolyArea(dtPolyRef ref, unsigned char area);
/// Gets the user defined area for the specified polygon.
/// @param[in] ref The polygon reference.
/// @param[out] resultArea The area id for the polygon.
/// @return The status flags for the operation.
dtStatus getPolyArea(dtPolyRef ref, unsigned char* resultArea) const;
/// Gets the size of the buffer required by #storeTileState to store the specified tile's state.
/// @param[in] tile The tile.
/// @return The size of the buffer required to store the state.
int getTileStateSize(const dtMeshTile* tile) const;
/// Stores the non-structural state of the tile in the specified buffer. (Flags, area ids, etc.)
/// @param[in] tile The tile.
/// @param[out] data The buffer to store the tile's state in.
/// @param[in] maxDataSize The size of the data buffer. [Limit: >= #getTileStateSize]
/// @return The status flags for the operation.
dtStatus storeTileState(const dtMeshTile* tile, unsigned char* data, const int maxDataSize) const;
/// Restores the state of the tile.
/// @param[in] tile The tile.
/// @param[in] data The new state. (Obtained from #storeTileState.)
/// @param[in] maxDataSize The size of the state within the data buffer.
/// @return The status flags for the operation.
dtStatus restoreTileState(dtMeshTile* tile, const unsigned char* data, const int maxDataSize);
/// @}
/// @{
/// @name Encoding and Decoding
/// These functions are generally meant for internal use only.
/// Derives a standard polygon reference.
/// @note This function is generally meant for internal use only.
/// @param[in] salt The tile's salt value.
/// @param[in] it The index of the tile.
/// @param[in] ip The index of the polygon within the tile.
inline dtPolyRef encodePolyId(unsigned int salt, unsigned int it, unsigned int ip) const
{
return ((dtPolyRef)salt << (m_polyBits+m_tileBits)) | ((dtPolyRef)it << m_polyBits) | (dtPolyRef)ip;
}
/// Decodes a standard polygon reference.
/// @note This function is generally meant for internal use only.
/// @param[in] ref The polygon reference to decode.
/// @param[out] salt The tile's salt value.
/// @param[out] it The index of the tile.
/// @param[out] ip The index of the polygon within the tile.
/// @see #encodePolyId
inline void decodePolyId(dtPolyRef ref, unsigned int& salt, unsigned int& it, unsigned int& ip) const
{
const dtPolyRef saltMask = ((dtPolyRef)1<<m_saltBits)-1;
const dtPolyRef tileMask = ((dtPolyRef)1<<m_tileBits)-1;
const dtPolyRef polyMask = ((dtPolyRef)1<<m_polyBits)-1;
salt = (unsigned int)((ref >> (m_polyBits+m_tileBits)) & saltMask);
it = (unsigned int)((ref >> m_polyBits) & tileMask);
ip = (unsigned int)(ref & polyMask);
}
/// Extracts a tile's salt value from the specified polygon reference.
/// @note This function is generally meant for internal use only.
/// @param[in] ref The polygon reference.
/// @see #encodePolyId
inline unsigned int decodePolyIdSalt(dtPolyRef ref) const
{
const dtPolyRef saltMask = ((dtPolyRef)1<<m_saltBits)-1;
return (unsigned int)((ref >> (m_polyBits+m_tileBits)) & saltMask);
}
/// Extracts the tile's index from the specified polygon reference.
/// @note This function is generally meant for internal use only.
/// @param[in] ref The polygon reference.
/// @see #encodePolyId
inline unsigned int decodePolyIdTile(dtPolyRef ref) const
{
const dtPolyRef tileMask = ((dtPolyRef)1<<m_tileBits)-1;
return (unsigned int)((ref >> m_polyBits) & tileMask);
}
/// Extracts the polygon's index (within its tile) from the specified polygon reference.
/// @note This function is generally meant for internal use only.
/// @param[in] ref The polygon reference.
/// @see #encodePolyId
inline unsigned int decodePolyIdPoly(dtPolyRef ref) const
{
const dtPolyRef polyMask = ((dtPolyRef)1<<m_polyBits)-1;
return (unsigned int)(ref & polyMask);
}
/// @}
private:
/// Returns pointer to tile in the tile array.
dtMeshTile* getTile(int i);
/// Returns neighbour tile based on side.
int getTilesAt(const int x, const int y,
dtMeshTile** tiles, const int maxTiles) const;
/// Returns neighbour tile based on side.
int getNeighbourTilesAt(const int x, const int y, const int side,
dtMeshTile** tiles, const int maxTiles) const;
/// Returns all polygons in neighbour tile based on portal defined by the segment.
int findConnectingPolys(const float* va, const float* vb,
const dtMeshTile* tile, int side,
dtPolyRef* con, float* conarea, int maxcon) const;
/// Builds internal polygons links for a tile.
void connectIntLinks(dtMeshTile* tile);
/// Builds internal polygons links for a tile.
void baseOffMeshLinks(dtMeshTile* tile);
/// Builds external polygon links for a tile.
void connectExtLinks(dtMeshTile* tile, dtMeshTile* target, int side);
/// Builds external polygon links for a tile.
void connectExtOffMeshLinks(dtMeshTile* tile, dtMeshTile* target, int side);
/// Removes external links at specified side.
void unconnectExtLinks(dtMeshTile* tile, dtMeshTile* target);
// TODO: These methods are duplicates from dtNavMeshQuery, but are needed for off-mesh connection finding.
/// Queries polygons within a tile.
int queryPolygonsInTile(const dtMeshTile* tile, const float* qmin, const float* qmax,
dtPolyRef* polys, const int maxPolys) const;
/// Find nearest polygon within a tile.
dtPolyRef findNearestPolyInTile(const dtMeshTile* tile, const float* center,
const float* extents, float* nearestPt) const;
/// Returns closest point on polygon.
void closestPointOnPoly(dtPolyRef ref, const float* pos, float* closest, bool* posOverPoly) const;
dtNavMeshParams m_params; ///< Current initialization params. TODO: do not store this info twice.
float m_orig[3]; ///< Origin of the tile (0,0)
float m_tileWidth, m_tileHeight; ///< Dimensions of each tile.
int m_maxTiles; ///< Max number of tiles.
int m_tileLutSize; ///< Tile hash lookup size (must be pot).
int m_tileLutMask; ///< Tile hash lookup mask.
dtMeshTile** m_posLookup; ///< Tile hash lookup.
dtMeshTile* m_nextFree; ///< Freelist of tiles.
dtMeshTile* m_tiles; ///< List of tiles.
unsigned int m_saltBits; ///< Number of salt bits in the tile ID.
unsigned int m_tileBits; ///< Number of tile bits in the tile ID.
unsigned int m_polyBits; ///< Number of poly bits in the tile ID.
};
/// Allocates a navigation mesh object using the Detour allocator.
/// @return A navigation mesh that is ready for initialization, or null on failure.
/// @ingroup detour
dtNavMesh* dtAllocNavMesh();
/// Frees the specified navigation mesh object using the Detour allocator.
/// @param[in] navmesh A navigation mesh allocated using #dtAllocNavMesh
/// @ingroup detour
void dtFreeNavMesh(dtNavMesh* navmesh);
#endif // DETOURNAVMESH_H
///////////////////////////////////////////////////////////////////////////
// This section contains detailed documentation for members that don't have
// a source file. It reduces clutter in the main section of the header.
/**
@typedef dtPolyRef
@par
Polygon references are subject to the same invalidate/preserve/restore
rules that apply to #dtTileRef's. If the #dtTileRef for the polygon's
tile changes, the polygon reference becomes invalid.
Changing a polygon's flags, area id, etc. does not impact its polygon
reference.
@typedef dtTileRef
@par
The following changes will invalidate a tile reference:
- The referenced tile has been removed from the navigation mesh.
- The navigation mesh has been initialized using a different set
of #dtNavMeshParams.
A tile reference is preserved/restored if the tile is added to a navigation
mesh initialized with the original #dtNavMeshParams and is added at the
original reference location. (E.g. The lastRef parameter is used with
dtNavMesh::addTile.)
Basically, if the storage structure of a tile changes, its associated
tile reference changes.
@var unsigned short dtPoly::neis[DT_VERTS_PER_POLYGON]
@par
Each entry represents data for the edge starting at the vertex of the same index.
E.g. The entry at index n represents the edge data for vertex[n] to vertex[n+1].
A value of zero indicates the edge has no polygon connection. (It makes up the
border of the navigation mesh.)
The information can be extracted as follows:
@code
neighborRef = neis[n] & 0xff; // Get the neighbor polygon reference.
if (neis[n] & #DT_EX_LINK)
{
// The edge is an external (portal) edge.
}
@endcode
@var float dtMeshHeader::bvQuantFactor
@par
This value is used for converting between world and bounding volume coordinates.
For example:
@code
const float cs = 1.0f / tile->header->bvQuantFactor;
const dtBVNode* n = &tile->bvTree[i];
if (n->i >= 0)
{
// This is a leaf node.
float worldMinX = tile->header->bmin[0] + n->bmin[0]*cs;
float worldMinY = tile->header->bmin[0] + n->bmin[1]*cs;
// Etc...
}
@endcode
@struct dtMeshTile
@par
Tiles generally only exist within the context of a dtNavMesh object.
Some tile content is optional. For example, a tile may not contain any
off-mesh connections. In this case the associated pointer will be null.
If a detail mesh exists it will share vertices with the base polygon mesh.
Only the vertices unique to the detail mesh will be stored in #detailVerts.
@warning Tiles returned by a dtNavMesh object are not guarenteed to be populated.
For example: The tile at a location might not have been loaded yet, or may have been removed.
In this case, pointers will be null. So if in doubt, check the polygon count in the
tile's header to determine if a tile has polygons defined.
@var float dtOffMeshConnection::pos[6]
@par
For a properly built navigation mesh, vertex A will always be within the bounds of the mesh.
Vertex B is not required to be within the bounds of the mesh.
*/

View File

@@ -0,0 +1,141 @@
//
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#ifndef DETOURNAVMESHBUILDER_H
#define DETOURNAVMESHBUILDER_H
#include "DetourAlloc.h"
/// Represents the source data used to build an navigation mesh tile.
/// @ingroup detour
struct dtNavMeshCreateParams
{
/// @name Polygon Mesh Attributes
/// Used to create the base navigation graph.
/// See #rcPolyMesh for details related to these attributes.
/// @{
const unsigned short* verts; ///< The polygon mesh vertices. [(x, y, z) * #vertCount] [Unit: vx]
int vertCount; ///< The number vertices in the polygon mesh. [Limit: >= 3]
const unsigned short* polys; ///< The polygon data. [Size: #polyCount * 2 * #nvp]
const unsigned short* polyFlags; ///< The user defined flags assigned to each polygon. [Size: #polyCount]
const unsigned char* polyAreas; ///< The user defined area ids assigned to each polygon. [Size: #polyCount]
int polyCount; ///< Number of polygons in the mesh. [Limit: >= 1]
int nvp; ///< Number maximum number of vertices per polygon. [Limit: >= 3]
/// @}
/// @name Height Detail Attributes (Optional)
/// See #rcPolyMeshDetail for details related to these attributes.
/// @{
const unsigned int* detailMeshes; ///< The height detail sub-mesh data. [Size: 4 * #polyCount]
const float* detailVerts; ///< The detail mesh vertices. [Size: 3 * #detailVertsCount] [Unit: wu]
int detailVertsCount; ///< The number of vertices in the detail mesh.
const unsigned char* detailTris; ///< The detail mesh triangles. [Size: 4 * #detailTriCount]
int detailTriCount; ///< The number of triangles in the detail mesh.
/// @}
/// @name Off-Mesh Connections Attributes (Optional)
/// Used to define a custom point-to-point edge within the navigation graph, an
/// off-mesh connection is a user defined traversable connection made up to two vertices,
/// at least one of which resides within a navigation mesh polygon.
/// @{
/// Off-mesh connection vertices. [(ax, ay, az, bx, by, bz) * #offMeshConCount] [Unit: wu]
const float* offMeshConVerts;
/// Off-mesh connection radii. [Size: #offMeshConCount] [Unit: wu]
const float* offMeshConRad;
/// User defined flags assigned to the off-mesh connections. [Size: #offMeshConCount]
const unsigned short* offMeshConFlags;
/// User defined area ids assigned to the off-mesh connections. [Size: #offMeshConCount]
const unsigned char* offMeshConAreas;
/// The permitted travel direction of the off-mesh connections. [Size: #offMeshConCount]
///
/// 0 = Travel only from endpoint A to endpoint B.<br/>
/// #DT_OFFMESH_CON_BIDIR = Bidirectional travel.
const unsigned char* offMeshConDir;
/// The user defined ids of the off-mesh connection. [Size: #offMeshConCount]
const unsigned int* offMeshConUserID;
/// The number of off-mesh connections. [Limit: >= 0]
int offMeshConCount;
/// @}
/// @name Tile Attributes
/// @note The tile grid/layer data can be left at zero if the destination is a single tile mesh.
/// @{
unsigned int userId; ///< The user defined id of the tile.
int tileX; ///< The tile's x-grid location within the multi-tile destination mesh. (Along the x-axis.)
int tileY; ///< The tile's y-grid location within the multi-tile desitation mesh. (Along the z-axis.)
int tileLayer; ///< The tile's layer within the layered destination mesh. [Limit: >= 0] (Along the y-axis.)
float bmin[3]; ///< The minimum bounds of the tile. [(x, y, z)] [Unit: wu]
float bmax[3]; ///< The maximum bounds of the tile. [(x, y, z)] [Unit: wu]
/// @}
/// @name General Configuration Attributes
/// @{
float walkableHeight; ///< The agent height. [Unit: wu]
float walkableRadius; ///< The agent radius. [Unit: wu]
float walkableClimb; ///< The agent maximum traversable ledge. (Up/Down) [Unit: wu]
float cs; ///< The xz-plane cell size of the polygon mesh. [Limit: > 0] [Unit: wu]
float ch; ///< The y-axis cell height of the polygon mesh. [Limit: > 0] [Unit: wu]
/// True if a bounding volume tree should be built for the tile.
/// @note The BVTree is not normally needed for layered navigation meshes.
bool buildBvTree;
/// @}
};
/// Builds navigation mesh tile data from the provided tile creation data.
/// @ingroup detour
/// @param[in] params Tile creation data.
/// @param[out] outData The resulting tile data.
/// @param[out] outDataSize The size of the tile data array.
/// @return True if the tile data was successfully created.
bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, int* outDataSize);
/// Swaps the endianess of the tile data's header (#dtMeshHeader).
/// @param[in,out] data The tile data array.
/// @param[in] dataSize The size of the data array.
bool dtNavMeshHeaderSwapEndian(unsigned char* data, const int dataSize);
/// Swaps endianess of the tile data.
/// @param[in,out] data The tile data array.
/// @param[in] dataSize The size of the data array.
bool dtNavMeshDataSwapEndian(unsigned char* data, const int dataSize);
#endif // DETOURNAVMESHBUILDER_H
// This section contains detailed documentation for members that don't have
// a source file. It reduces clutter in the main section of the header.
/**
@struct dtNavMeshCreateParams
@par
This structure is used to marshal data between the Recast mesh generation pipeline and Detour navigation components.
See the rcPolyMesh and rcPolyMeshDetail documentation for detailed information related to mesh structure.
Units are usually in voxels (vx) or world units (wu). The units for voxels, grid size, and cell size
are all based on the values of #cs and #ch.
The standard navigation mesh build process is to create tile data using dtCreateNavMeshData, then add the tile
to a navigation mesh using either the dtNavMesh single tile <tt>init()</tt> function or the dtNavMesh::addTile()
function.
@see dtCreateNavMeshData
*/

View File

@@ -0,0 +1,536 @@
//
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#ifndef DETOURNAVMESHQUERY_H
#define DETOURNAVMESHQUERY_H
#include "DetourNavMesh.h"
#include "DetourStatus.h"
// Define DT_VIRTUAL_QUERYFILTER if you wish to derive a custom filter from dtQueryFilter.
// On certain platforms indirect or virtual function call is expensive. The default
// setting is to use non-virtual functions, the actual implementations of the functions
// are declared as inline for maximum speed.
//#define DT_VIRTUAL_QUERYFILTER 1
/// Defines polygon filtering and traversal costs for navigation mesh query operations.
/// @ingroup detour
class dtQueryFilter
{
float m_areaCost[DT_MAX_AREAS]; ///< Cost per area type. (Used by default implementation.)
unsigned short m_includeFlags; ///< Flags for polygons that can be visited. (Used by default implementation.)
unsigned short m_excludeFlags; ///< Flags for polygons that should not be visted. (Used by default implementation.)
public:
dtQueryFilter();
#ifdef DT_VIRTUAL_QUERYFILTER
virtual ~dtQueryFilter() { }
#endif
/// Returns true if the polygon can be visited. (I.e. Is traversable.)
/// @param[in] ref The reference id of the polygon test.
/// @param[in] tile The tile containing the polygon.
/// @param[in] poly The polygon to test.
#ifdef DT_VIRTUAL_QUERYFILTER
virtual bool passFilter(const dtPolyRef ref,
const dtMeshTile* tile,
const dtPoly* poly) const;
#else
bool passFilter(const dtPolyRef ref,
const dtMeshTile* tile,
const dtPoly* poly) const;
#endif
/// Returns cost to move from the beginning to the end of a line segment
/// that is fully contained within a polygon.
/// @param[in] pa The start position on the edge of the previous and current polygon. [(x, y, z)]
/// @param[in] pb The end position on the edge of the current and next polygon. [(x, y, z)]
/// @param[in] prevRef The reference id of the previous polygon. [opt]
/// @param[in] prevTile The tile containing the previous polygon. [opt]
/// @param[in] prevPoly The previous polygon. [opt]
/// @param[in] curRef The reference id of the current polygon.
/// @param[in] curTile The tile containing the current polygon.
/// @param[in] curPoly The current polygon.
/// @param[in] nextRef The refernece id of the next polygon. [opt]
/// @param[in] nextTile The tile containing the next polygon. [opt]
/// @param[in] nextPoly The next polygon. [opt]
#ifdef DT_VIRTUAL_QUERYFILTER
virtual float getCost(const float* pa, const float* pb,
const dtPolyRef prevRef, const dtMeshTile* prevTile, const dtPoly* prevPoly,
const dtPolyRef curRef, const dtMeshTile* curTile, const dtPoly* curPoly,
const dtPolyRef nextRef, const dtMeshTile* nextTile, const dtPoly* nextPoly) const;
#else
float getCost(const float* pa, const float* pb,
const dtPolyRef prevRef, const dtMeshTile* prevTile, const dtPoly* prevPoly,
const dtPolyRef curRef, const dtMeshTile* curTile, const dtPoly* curPoly,
const dtPolyRef nextRef, const dtMeshTile* nextTile, const dtPoly* nextPoly) const;
#endif
/// @name Getters and setters for the default implementation data.
///@{
/// Returns the traversal cost of the area.
/// @param[in] i The id of the area.
/// @returns The traversal cost of the area.
inline float getAreaCost(const int i) const { return m_areaCost[i]; }
/// Sets the traversal cost of the area.
/// @param[in] i The id of the area.
/// @param[in] cost The new cost of traversing the area.
inline void setAreaCost(const int i, const float cost) { m_areaCost[i] = cost; }
/// Returns the include flags for the filter.
/// Any polygons that include one or more of these flags will be
/// included in the operation.
inline unsigned short getIncludeFlags() const { return m_includeFlags; }
/// Sets the include flags for the filter.
/// @param[in] flags The new flags.
inline void setIncludeFlags(const unsigned short flags) { m_includeFlags = flags; }
/// Returns the exclude flags for the filter.
/// Any polygons that include one ore more of these flags will be
/// excluded from the operation.
inline unsigned short getExcludeFlags() const { return m_excludeFlags; }
/// Sets the exclude flags for the filter.
/// @param[in] flags The new flags.
inline void setExcludeFlags(const unsigned short flags) { m_excludeFlags = flags; }
///@}
};
/// Provides information about raycast hit
/// filled by dtNavMeshQuery::raycast
/// @ingroup detour
struct dtRaycastHit
{
/// The hit parameter. (FLT_MAX if no wall hit.)
float t;
/// hitNormal The normal of the nearest wall hit. [(x, y, z)]
float hitNormal[3];
/// Pointer to an array of reference ids of the visited polygons. [opt]
dtPolyRef* path;
/// The number of visited polygons. [opt]
int pathCount;
/// The maximum number of polygons the @p path array can hold.
int maxPath;
/// The cost of the path until hit.
float pathCost;
};
/// Provides the ability to perform pathfinding related queries against
/// a navigation mesh.
/// @ingroup detour
class dtNavMeshQuery
{
public:
dtNavMeshQuery();
~dtNavMeshQuery();
/// Initializes the query object.
/// @param[in] nav Pointer to the dtNavMesh object to use for all queries.
/// @param[in] maxNodes Maximum number of search nodes. [Limits: 0 < value <= 65536]
/// @returns The status flags for the query.
dtStatus init(const dtNavMesh* nav, const int maxNodes);
/// @name Standard Pathfinding Functions
// /@{
/// Finds a path from the start polygon to the end polygon.
/// @param[in] startRef The refrence id of the start polygon.
/// @param[in] endRef The reference id of the end polygon.
/// @param[in] startPos A position within the start polygon. [(x, y, z)]
/// @param[in] endPos A position within the end polygon. [(x, y, z)]
/// @param[in] filter The polygon filter to apply to the query.
/// @param[out] path An ordered list of polygon references representing the path. (Start to end.)
/// [(polyRef) * @p pathCount]
/// @param[out] pathCount The number of polygons returned in the @p path array.
/// @param[in] maxPath The maximum number of polygons the @p path array can hold. [Limit: >= 1]
dtStatus findPath(dtPolyRef startRef, dtPolyRef endRef,
const float* startPos, const float* endPos,
const dtQueryFilter* filter,
dtPolyRef* path, int* pathCount, const int maxPath) const;
/// Finds the straight path from the start to the end position within the polygon corridor.
/// @param[in] startPos Path start position. [(x, y, z)]
/// @param[in] endPos Path end position. [(x, y, z)]
/// @param[in] path An array of polygon references that represent the path corridor.
/// @param[in] pathSize The number of polygons in the @p path array.
/// @param[out] straightPath Points describing the straight path. [(x, y, z) * @p straightPathCount].
/// @param[out] straightPathFlags Flags describing each point. (See: #dtStraightPathFlags) [opt]
/// @param[out] straightPathRefs The reference id of the polygon that is being entered at each point. [opt]
/// @param[out] straightPathCount The number of points in the straight path.
/// @param[in] maxStraightPath The maximum number of points the straight path arrays can hold. [Limit: > 0]
/// @param[in] options Query options. (see: #dtStraightPathOptions)
/// @returns The status flags for the query.
dtStatus findStraightPath(const float* startPos, const float* endPos,
const dtPolyRef* path, const int pathSize,
float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs,
int* straightPathCount, const int maxStraightPath, const int options = 0) const;
///@}
/// @name Sliced Pathfinding Functions
/// Common use case:
/// -# Call initSlicedFindPath() to initialize the sliced path query.
/// -# Call updateSlicedFindPath() until it returns complete.
/// -# Call finalizeSlicedFindPath() to get the path.
///@{
/// Intializes a sliced path query.
/// @param[in] startRef The refrence id of the start polygon.
/// @param[in] endRef The reference id of the end polygon.
/// @param[in] startPos A position within the start polygon. [(x, y, z)]
/// @param[in] endPos A position within the end polygon. [(x, y, z)]
/// @param[in] filter The polygon filter to apply to the query.
/// @param[in] options query options (see: #dtFindPathOptions)
/// @returns The status flags for the query.
dtStatus initSlicedFindPath(dtPolyRef startRef, dtPolyRef endRef,
const float* startPos, const float* endPos,
const dtQueryFilter* filter, const unsigned int options = 0);
/// Updates an in-progress sliced path query.
/// @param[in] maxIter The maximum number of iterations to perform.
/// @param[out] doneIters The actual number of iterations completed. [opt]
/// @returns The status flags for the query.
dtStatus updateSlicedFindPath(const int maxIter, int* doneIters);
/// Finalizes and returns the results of a sliced path query.
/// @param[out] path An ordered list of polygon references representing the path. (Start to end.)
/// [(polyRef) * @p pathCount]
/// @param[out] pathCount The number of polygons returned in the @p path array.
/// @param[in] maxPath The max number of polygons the path array can hold. [Limit: >= 1]
/// @returns The status flags for the query.
dtStatus finalizeSlicedFindPath(dtPolyRef* path, int* pathCount, const int maxPath);
/// Finalizes and returns the results of an incomplete sliced path query, returning the path to the furthest
/// polygon on the existing path that was visited during the search.
/// @param[in] existing An array of polygon references for the existing path.
/// @param[in] existingSize The number of polygon in the @p existing array.
/// @param[out] path An ordered list of polygon references representing the path. (Start to end.)
/// [(polyRef) * @p pathCount]
/// @param[out] pathCount The number of polygons returned in the @p path array.
/// @param[in] maxPath The max number of polygons the @p path array can hold. [Limit: >= 1]
/// @returns The status flags for the query.
dtStatus finalizeSlicedFindPathPartial(const dtPolyRef* existing, const int existingSize,
dtPolyRef* path, int* pathCount, const int maxPath);
///@}
/// @name Dijkstra Search Functions
/// @{
/// Finds the polygons along the navigation graph that touch the specified circle.
/// @param[in] startRef The reference id of the polygon where the search starts.
/// @param[in] centerPos The center of the search circle. [(x, y, z)]
/// @param[in] radius The radius of the search circle.
/// @param[in] filter The polygon filter to apply to the query.
/// @param[out] resultRef The reference ids of the polygons touched by the circle. [opt]
/// @param[out] resultParent The reference ids of the parent polygons for each result.
/// Zero if a result polygon has no parent. [opt]
/// @param[out] resultCost The search cost from @p centerPos to the polygon. [opt]
/// @param[out] resultCount The number of polygons found. [opt]
/// @param[in] maxResult The maximum number of polygons the result arrays can hold.
/// @returns The status flags for the query.
dtStatus findPolysAroundCircle(dtPolyRef startRef, const float* centerPos, const float radius,
const dtQueryFilter* filter,
dtPolyRef* resultRef, dtPolyRef* resultParent, float* resultCost,
int* resultCount, const int maxResult) const;
/// Finds the polygons along the naviation graph that touch the specified convex polygon.
/// @param[in] startRef The reference id of the polygon where the search starts.
/// @param[in] verts The vertices describing the convex polygon. (CCW)
/// [(x, y, z) * @p nverts]
/// @param[in] nverts The number of vertices in the polygon.
/// @param[in] filter The polygon filter to apply to the query.
/// @param[out] resultRef The reference ids of the polygons touched by the search polygon. [opt]
/// @param[out] resultParent The reference ids of the parent polygons for each result. Zero if a
/// result polygon has no parent. [opt]
/// @param[out] resultCost The search cost from the centroid point to the polygon. [opt]
/// @param[out] resultCount The number of polygons found.
/// @param[in] maxResult The maximum number of polygons the result arrays can hold.
/// @returns The status flags for the query.
dtStatus findPolysAroundShape(dtPolyRef startRef, const float* verts, const int nverts,
const dtQueryFilter* filter,
dtPolyRef* resultRef, dtPolyRef* resultParent, float* resultCost,
int* resultCount, const int maxResult) const;
/// @}
/// @name Local Query Functions
///@{
/// Finds the polygon nearest to the specified center point.
/// @param[in] center The center of the search box. [(x, y, z)]
/// @param[in] extents The search distance along each axis. [(x, y, z)]
/// @param[in] filter The polygon filter to apply to the query.
/// @param[out] nearestRef The reference id of the nearest polygon.
/// @param[out] nearestPt The nearest point on the polygon. [opt] [(x, y, z)]
/// @returns The status flags for the query.
dtStatus findNearestPoly(const float* center, const float* extents,
const dtQueryFilter* filter,
dtPolyRef* nearestRef, float* nearestPt) const;
/// Finds polygons that overlap the search box.
/// @param[in] center The center of the search box. [(x, y, z)]
/// @param[in] extents The search distance along each axis. [(x, y, z)]
/// @param[in] filter The polygon filter to apply to the query.
/// @param[out] polys The reference ids of the polygons that overlap the query box.
/// @param[out] polyCount The number of polygons in the search result.
/// @param[in] maxPolys The maximum number of polygons the search result can hold.
/// @returns The status flags for the query.
dtStatus queryPolygons(const float* center, const float* extents,
const dtQueryFilter* filter,
dtPolyRef* polys, int* polyCount, const int maxPolys) const;
/// Finds the non-overlapping navigation polygons in the local neighbourhood around the center position.
/// @param[in] startRef The reference id of the polygon where the search starts.
/// @param[in] centerPos The center of the query circle. [(x, y, z)]
/// @param[in] radius The radius of the query circle.
/// @param[in] filter The polygon filter to apply to the query.
/// @param[out] resultRef The reference ids of the polygons touched by the circle.
/// @param[out] resultParent The reference ids of the parent polygons for each result.
/// Zero if a result polygon has no parent. [opt]
/// @param[out] resultCount The number of polygons found.
/// @param[in] maxResult The maximum number of polygons the result arrays can hold.
/// @returns The status flags for the query.
dtStatus findLocalNeighbourhood(dtPolyRef startRef, const float* centerPos, const float radius,
const dtQueryFilter* filter,
dtPolyRef* resultRef, dtPolyRef* resultParent,
int* resultCount, const int maxResult) const;
/// Moves from the start to the end position constrained to the navigation mesh.
/// @param[in] startRef The reference id of the start polygon.
/// @param[in] startPos A position of the mover within the start polygon. [(x, y, x)]
/// @param[in] endPos The desired end position of the mover. [(x, y, z)]
/// @param[in] filter The polygon filter to apply to the query.
/// @param[out] resultPos The result position of the mover. [(x, y, z)]
/// @param[out] visited The reference ids of the polygons visited during the move.
/// @param[out] visitedCount The number of polygons visited during the move.
/// @param[in] maxVisitedSize The maximum number of polygons the @p visited array can hold.
/// @returns The status flags for the query.
dtStatus moveAlongSurface(dtPolyRef startRef, const float* startPos, const float* endPos,
const dtQueryFilter* filter,
float* resultPos, dtPolyRef* visited, int* visitedCount, const int maxVisitedSize) const;
/// Casts a 'walkability' ray along the surface of the navigation mesh from
/// the start position toward the end position.
/// @note A wrapper around raycast(..., RaycastHit*). Retained for backward compatibility.
/// @param[in] startRef The reference id of the start polygon.
/// @param[in] startPos A position within the start polygon representing
/// the start of the ray. [(x, y, z)]
/// @param[in] endPos The position to cast the ray toward. [(x, y, z)]
/// @param[out] t The hit parameter. (FLT_MAX if no wall hit.)
/// @param[out] hitNormal The normal of the nearest wall hit. [(x, y, z)]
/// @param[in] filter The polygon filter to apply to the query.
/// @param[out] path The reference ids of the visited polygons. [opt]
/// @param[out] pathCount The number of visited polygons. [opt]
/// @param[in] maxPath The maximum number of polygons the @p path array can hold.
/// @returns The status flags for the query.
dtStatus raycast(dtPolyRef startRef, const float* startPos, const float* endPos,
const dtQueryFilter* filter,
float* t, float* hitNormal, dtPolyRef* path, int* pathCount, const int maxPath) const;
/// Casts a 'walkability' ray along the surface of the navigation mesh from
/// the start position toward the end position.
/// @param[in] startRef The reference id of the start polygon.
/// @param[in] startPos A position within the start polygon representing
/// the start of the ray. [(x, y, z)]
/// @param[in] endPos The position to cast the ray toward. [(x, y, z)]
/// @param[in] filter The polygon filter to apply to the query.
/// @param[in] flags govern how the raycast behaves. See dtRaycastOptions
/// @param[out] hit Pointer to a raycast hit structure which will be filled by the results.
/// @param[in] prevRef parent of start ref. Used during for cost calculation [opt]
/// @returns The status flags for the query.
dtStatus raycast(dtPolyRef startRef, const float* startPos, const float* endPos,
const dtQueryFilter* filter, const unsigned int options,
dtRaycastHit* hit, dtPolyRef prevRef = 0) const;
/// Finds the distance from the specified position to the nearest polygon wall.
/// @param[in] startRef The reference id of the polygon containing @p centerPos.
/// @param[in] centerPos The center of the search circle. [(x, y, z)]
/// @param[in] maxRadius The radius of the search circle.
/// @param[in] filter The polygon filter to apply to the query.
/// @param[out] hitDist The distance to the nearest wall from @p centerPos.
/// @param[out] hitPos The nearest position on the wall that was hit. [(x, y, z)]
/// @param[out] hitNormal The normalized ray formed from the wall point to the
/// source point. [(x, y, z)]
/// @returns The status flags for the query.
dtStatus findDistanceToWall(dtPolyRef startRef, const float* centerPos, const float maxRadius,
const dtQueryFilter* filter,
float* hitDist, float* hitPos, float* hitNormal) const;
/// Returns the segments for the specified polygon, optionally including portals.
/// @param[in] ref The reference id of the polygon.
/// @param[in] filter The polygon filter to apply to the query.
/// @param[out] segmentVerts The segments. [(ax, ay, az, bx, by, bz) * segmentCount]
/// @param[out] segmentRefs The reference ids of each segment's neighbor polygon.
/// Or zero if the segment is a wall. [opt] [(parentRef) * @p segmentCount]
/// @param[out] segmentCount The number of segments returned.
/// @param[in] maxSegments The maximum number of segments the result arrays can hold.
/// @returns The status flags for the query.
dtStatus getPolyWallSegments(dtPolyRef ref, const dtQueryFilter* filter,
float* segmentVerts, dtPolyRef* segmentRefs, int* segmentCount,
const int maxSegments) const;
/// Returns random location on navmesh.
/// Polygons are chosen weighted by area. The search runs in linear related to number of polygon.
/// @param[in] filter The polygon filter to apply to the query.
/// @param[in] frand Function returning a random number [0..1).
/// @param[out] randomRef The reference id of the random location.
/// @param[out] randomPt The random location.
/// @returns The status flags for the query.
dtStatus findRandomPoint(const dtQueryFilter* filter, float (*frand)(),
dtPolyRef* randomRef, float* randomPt) const;
/// Returns random location on navmesh within the reach of specified location.
/// Polygons are chosen weighted by area. The search runs in linear related to number of polygon.
/// The location is not exactly constrained by the circle, but it limits the visited polygons.
/// @param[in] startRef The reference id of the polygon where the search starts.
/// @param[in] centerPos The center of the search circle. [(x, y, z)]
/// @param[in] filter The polygon filter to apply to the query.
/// @param[in] frand Function returning a random number [0..1).
/// @param[out] randomRef The reference id of the random location.
/// @param[out] randomPt The random location. [(x, y, z)]
/// @returns The status flags for the query.
dtStatus findRandomPointAroundCircle(dtPolyRef startRef, const float* centerPos, const float maxRadius,
const dtQueryFilter* filter, float (*frand)(),
dtPolyRef* randomRef, float* randomPt) const;
/// Finds the closest point on the specified polygon.
/// @param[in] ref The reference id of the polygon.
/// @param[in] pos The position to check. [(x, y, z)]
/// @param[out] closest The closest point on the polygon. [(x, y, z)]
/// @param[out] posOverPoly True of the position is over the polygon.
/// @returns The status flags for the query.
dtStatus closestPointOnPoly(dtPolyRef ref, const float* pos, float* closest, bool* posOverPoly) const;
/// Returns a point on the boundary closest to the source point if the source point is outside the
/// polygon's xz-bounds.
/// @param[in] ref The reference id to the polygon.
/// @param[in] pos The position to check. [(x, y, z)]
/// @param[out] closest The closest point. [(x, y, z)]
/// @returns The status flags for the query.
dtStatus closestPointOnPolyBoundary(dtPolyRef ref, const float* pos, float* closest) const;
/// Gets the height of the polygon at the provided position using the height detail. (Most accurate.)
/// @param[in] ref The reference id of the polygon.
/// @param[in] pos A position within the xz-bounds of the polygon. [(x, y, z)]
/// @param[out] height The height at the surface of the polygon.
/// @returns The status flags for the query.
dtStatus getPolyHeight(dtPolyRef ref, const float* pos, float* height) const;
/// @}
/// @name Miscellaneous Functions
/// @{
/// Returns true if the polygon reference is valid and passes the filter restrictions.
/// @param[in] ref The polygon reference to check.
/// @param[in] filter The filter to apply.
bool isValidPolyRef(dtPolyRef ref, const dtQueryFilter* filter) const;
/// Returns true if the polygon reference is in the closed list.
/// @param[in] ref The reference id of the polygon to check.
/// @returns True if the polygon is in closed list.
bool isInClosedList(dtPolyRef ref) const;
/// Gets the node pool.
/// @returns The node pool.
class dtNodePool* getNodePool() const { return m_nodePool; }
/// Gets the navigation mesh the query object is using.
/// @return The navigation mesh the query object is using.
const dtNavMesh* getAttachedNavMesh() const { return m_nav; }
/// @}
private:
/// Returns neighbour tile based on side.
dtMeshTile* getNeighbourTileAt(int x, int y, int side) const;
/// Queries polygons within a tile.
int queryPolygonsInTile(const dtMeshTile* tile, const float* qmin, const float* qmax, const dtQueryFilter* filter,
dtPolyRef* polys, const int maxPolys) const;
/// Returns portal points between two polygons.
dtStatus getPortalPoints(dtPolyRef from, dtPolyRef to, float* left, float* right,
unsigned char& fromType, unsigned char& toType) const;
dtStatus getPortalPoints(dtPolyRef from, const dtPoly* fromPoly, const dtMeshTile* fromTile,
dtPolyRef to, const dtPoly* toPoly, const dtMeshTile* toTile,
float* left, float* right) const;
/// Returns edge mid point between two polygons.
dtStatus getEdgeMidPoint(dtPolyRef from, dtPolyRef to, float* mid) const;
dtStatus getEdgeMidPoint(dtPolyRef from, const dtPoly* fromPoly, const dtMeshTile* fromTile,
dtPolyRef to, const dtPoly* toPoly, const dtMeshTile* toTile,
float* mid) const;
// Appends vertex to a straight path
dtStatus appendVertex(const float* pos, const unsigned char flags, const dtPolyRef ref,
float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs,
int* straightPathCount, const int maxStraightPath) const;
// Appends intermediate portal points to a straight path.
dtStatus appendPortals(const int startIdx, const int endIdx, const float* endPos, const dtPolyRef* path,
float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs,
int* straightPathCount, const int maxStraightPath, const int options) const;
const dtNavMesh* m_nav; ///< Pointer to navmesh data.
struct dtQueryData
{
dtStatus status;
struct dtNode* lastBestNode;
float lastBestNodeCost;
dtPolyRef startRef, endRef;
float startPos[3], endPos[3];
const dtQueryFilter* filter;
unsigned int options;
float raycastLimitSqr;
};
dtQueryData m_query; ///< Sliced query state.
class dtNodePool* m_tinyNodePool; ///< Pointer to small node pool.
class dtNodePool* m_nodePool; ///< Pointer to node pool.
class dtNodeQueue* m_openList; ///< Pointer to open list queue.
};
/// Allocates a query object using the Detour allocator.
/// @return An allocated query object, or null on failure.
/// @ingroup detour
dtNavMeshQuery* dtAllocNavMeshQuery();
/// Frees the specified query object using the Detour allocator.
/// @param[in] query A query object allocated using #dtAllocNavMeshQuery
/// @ingroup detour
void dtFreeNavMeshQuery(dtNavMeshQuery* query);
#endif // DETOURNAVMESHQUERY_H

View File

@@ -25,22 +25,28 @@ enum dtNodeFlags
{
DT_NODE_OPEN = 0x01,
DT_NODE_CLOSED = 0x02,
DT_NODE_PARENT_DETACHED = 0x04, // parent of the node is not adjacent. Found using raycast.
};
typedef unsigned short dtNodeIndex;
static const dtNodeIndex DT_NULL_IDX = ~0;
static const dtNodeIndex DT_NULL_IDX = (dtNodeIndex)~0;
struct dtNode
{
float pos[3]; // Position of the node.
float cost; // Cost from previous node to current node.
float total; // Cost up to the node.
unsigned int pidx : 30; // Index to parent node.
unsigned int flags : 2; // Node flags 0/open/closed.
dtPolyRef id; // Polygon ref the node corresponds to.
float pos[3]; ///< Position of the node.
float cost; ///< Cost from previous node to current node.
float total; ///< Cost up to the node.
unsigned int pidx : 24; ///< Index to parent node.
unsigned int state : 2; ///< extra state information. A polyRef can have multiple nodes with different extra info. see DT_MAX_STATES_PER_NODE
unsigned int flags : 3; ///< Node flags. A combination of dtNodeFlags.
dtPolyRef id; ///< Polygon ref the node corresponds to.
};
static const int DT_MAX_STATES_PER_NODE = 4; // number of extra states per node. See dtNode::state
class dtNodePool
{
public:
@@ -48,8 +54,12 @@ public:
~dtNodePool();
inline void operator=(const dtNodePool&) {}
void clear();
dtNode* getNode(dtPolyRef id);
dtNode* findNode(dtPolyRef id);
// Get a dtNode by ref and extra state information. If there is none then - allocate
// There can be more than one node for the same polyRef but with different extra state information
dtNode* getNode(dtPolyRef id, unsigned char state=0);
dtNode* findNode(dtPolyRef id, unsigned char state);
unsigned int findNodes(dtPolyRef id, dtNode** nodes, const int maxNodes);
inline unsigned int getNodeIdx(const dtNode* node) const
{
@@ -82,6 +92,7 @@ public:
inline int getHashSize() const { return m_hashSize; }
inline dtNodeIndex getFirst(int bucket) const { return m_first[bucket]; }
inline dtNodeIndex getNext(int i) const { return m_next[i]; }
inline int getNodeCount() const { return m_nodeCount; }
private:
@@ -156,4 +167,4 @@ private:
};
#endif // DETOURNODE_H
#endif // DETOURNODE_H

View File

@@ -0,0 +1,64 @@
//
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#ifndef DETOURSTATUS_H
#define DETOURSTATUS_H
typedef unsigned int dtStatus;
// High level status.
static const unsigned int DT_FAILURE = 1u << 31; // Operation failed.
static const unsigned int DT_SUCCESS = 1u << 30; // Operation succeed.
static const unsigned int DT_IN_PROGRESS = 1u << 29; // Operation still in progress.
// Detail information for status.
static const unsigned int DT_STATUS_DETAIL_MASK = 0x0ffffff;
static const unsigned int DT_WRONG_MAGIC = 1 << 0; // Input data is not recognized.
static const unsigned int DT_WRONG_VERSION = 1 << 1; // Input data is in wrong version.
static const unsigned int DT_OUT_OF_MEMORY = 1 << 2; // Operation ran out of memory.
static const unsigned int DT_INVALID_PARAM = 1 << 3; // An input parameter was invalid.
static const unsigned int DT_BUFFER_TOO_SMALL = 1 << 4; // Result buffer for the query was too small to store all results.
static const unsigned int DT_OUT_OF_NODES = 1 << 5; // Query ran out of nodes during search.
static const unsigned int DT_PARTIAL_RESULT = 1 << 6; // Query did not reach the end location, returning best guess.
// Returns true of status is success.
inline bool dtStatusSucceed(dtStatus status)
{
return (status & DT_SUCCESS) != 0;
}
// Returns true of status is failure.
inline bool dtStatusFailed(dtStatus status)
{
return (status & DT_FAILURE) != 0;
}
// Returns true of status is in progress.
inline bool dtStatusInProgress(dtStatus status)
{
return (status & DT_IN_PROGRESS) != 0;
}
// Returns true if specific detail is set.
inline bool dtStatusDetail(dtStatus status, unsigned int detail)
{
return (status & detail) != 0;
}
#endif // DETOURSTATUS_H

View File

@@ -16,16 +16,11 @@
// 3. This notice may not be removed or altered from any source distribution.
//
#include <math.h>
#include "DetourCommon.h"
#include "DetourMath.h"
//////////////////////////////////////////////////////////////////////////////////////////
float dtSqrt(float x)
{
return sqrtf(x);
}
void dtClosestPtPointTriangle(float* closest, const float* p,
const float* a, const float* b, const float* c)
{
@@ -238,6 +233,9 @@ bool dtClosestHeightPointTriangle(const float* p, const float* a, const float* b
return false;
}
/// @par
///
/// All points are projected onto the xz-plane, so the y-values are ignored.
bool dtPointInPolygon(const float* pt, const float* verts, const int nverts)
{
// TODO: Replace pnpoly with triArea2D tests?
@@ -291,6 +289,9 @@ inline bool overlapRange(const float amin, const float amax,
return ((amin+eps) > bmax || (amax-eps) < bmin) ? false : true;
}
/// @par
///
/// All vertices are projected onto the xz-plane, so the y-values are ignored.
bool dtOverlapPolyPoly2D(const float* polya, const int npolya,
const float* polyb, const int npolyb)
{
@@ -327,3 +328,60 @@ bool dtOverlapPolyPoly2D(const float* polya, const int npolya,
return true;
}
// Returns a random point in a convex polygon.
// Adapted from Graphics Gems article.
void dtRandomPointInConvexPoly(const float* pts, const int npts, float* areas,
const float s, const float t, float* out)
{
// Calc triangle araes
float areasum = 0.0f;
for (int i = 2; i < npts; i++) {
areas[i] = dtTriArea2D(&pts[0], &pts[(i-1)*3], &pts[i*3]);
areasum += dtMax(0.001f, areas[i]);
}
// Find sub triangle weighted by area.
const float thr = s*areasum;
float acc = 0.0f;
float u = 0.0f;
int tri = 0;
for (int i = 2; i < npts; i++) {
const float dacc = areas[i];
if (thr >= acc && thr < (acc+dacc))
{
u = (thr - acc) / dacc;
tri = i;
break;
}
acc += dacc;
}
float v = dtMathSqrtf(t);
const float a = 1 - v;
const float b = (1 - u) * v;
const float c = u * v;
const float* pa = &pts[0];
const float* pb = &pts[(tri-1)*3];
const float* pc = &pts[tri*3];
out[0] = a*pa[0] + b*pb[0] + c*pc[0];
out[1] = a*pa[1] + b*pb[1] + c*pc[1];
out[2] = a*pa[2] + b*pb[2] + c*pc[2];
}
inline float vperpXZ(const float* a, const float* b) { return a[0]*b[2] - a[2]*b[0]; }
bool dtIntersectSegSeg2D(const float* ap, const float* aq,
const float* bp, const float* bq,
float& s, float& t)
{
float u[3], v[3], w[3];
dtVsub(u,aq,ap);
dtVsub(v,bq,bp);
dtVsub(w,ap,bp);
float d = vperpXZ(u,v);
if (fabsf(d) < 1e-6f) return false;
s = vperpXZ(v,w) / d;
t = vperpXZ(u,w) / d;
return true;
}

View File

@@ -16,12 +16,13 @@
// 3. This notice may not be removed or altered from any source distribution.
//
#include <math.h>
#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"
@@ -201,8 +202,8 @@ static int createBVTree(const unsigned short* verts, const int /*nverts*/,
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);
it.bmin[1] = (unsigned short)dtMathFloorf((float)it.bmin[1]*ch/cs);
it.bmax[1] = (unsigned short)dtMathCeilf((float)it.bmax[1]*ch/cs);
}
int curNode = 0;
@@ -237,11 +238,19 @@ static unsigned char classifyOffMeshPoint(const float* pt, const float* bmin, co
case ZM: return 6;
case XP|ZM: return 7;
};
return 0xff;
}
// TODO: Better error handling.
/// @par
///
/// The output data array is allocated using the detour allocator (dtAlloc()). The method
/// used to free the memory will be determined by how the tile is added to the navigation
/// mesh.
///
/// @see dtNavMesh, dtNavMesh::addTile()
bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, int* outDataSize)
{
if (params->nvp > DT_VERTS_PER_POLYGON)
@@ -252,8 +261,6 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
return false;
if (!params->polyCount || !params->polys)
return false;
//if (!params->detailMeshes || !params->detailVerts || !params->detailTris)
// return false;
const int nvp = params->nvp;
@@ -269,10 +276,50 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
if (!offMeshConClass)
return false;
// Find tight heigh bounds, used for culling out off-mesh start locations.
float hmin = FLT_MAX;
float hmax = -FLT_MAX;
if (params->detailVerts && params->detailVertsCount)
{
for (int i = 0; i < params->detailVertsCount; ++i)
{
const float h = params->detailVerts[i*3+1];
hmin = dtMin(hmin,h);
hmax = dtMax(hmax,h);
}
}
else
{
for (int i = 0; i < params->vertCount; ++i)
{
const unsigned short* iv = &params->verts[i*3];
const float h = params->bmin[1] + iv[1] * params->ch;
hmin = dtMin(hmin,h);
hmax = dtMax(hmax,h);
}
}
hmin -= params->walkableClimb;
hmax += params->walkableClimb;
float bmin[3], bmax[3];
dtVcopy(bmin, params->bmin);
dtVcopy(bmax, params->bmax);
bmin[1] = hmin;
bmax[1] = hmax;
for (int i = 0; i < params->offMeshConCount; ++i)
{
offMeshConClass[i*2+0] = classifyOffMeshPoint(&params->offMeshConVerts[(i*2+0)*3], params->bmin, params->bmax);
offMeshConClass[i*2+1] = classifyOffMeshPoint(&params->offMeshConVerts[(i*2+1)*3], params->bmin, params->bmax);
const float* p0 = &params->offMeshConVerts[(i*2+0)*3];
const float* p1 = &params->offMeshConVerts[(i*2+1)*3];
offMeshConClass[i*2+0] = classifyOffMeshPoint(p0, bmin, bmax);
offMeshConClass[i*2+1] = classifyOffMeshPoint(p1, bmin, bmax);
// Zero out off-mesh start positions which are not even potentially touching the mesh.
if (offMeshConClass[i*2+0] == 0xff)
{
if (p0[1] < bmin[1] || p0[1] > bmax[1])
offMeshConClass[i*2+0] = 0;
}
// Cound how many links should be allocated for off-mesh connections.
if (offMeshConClass[i*2+0] == 0xff)
@@ -298,23 +345,13 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
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 = &params->verts[p[j]*3];
const unsigned short* vb = &params->verts[p[nj]*3];
edgeCount++;
if (params->tileSize > 0)
if (p[nvp+j] & 0x8000)
{
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-
unsigned short dir = p[nvp+j] & 0xf;
if (dir != 0xf)
portalCount++;
}
}
}
@@ -368,7 +405,7 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
const int detailMeshesSize = dtAlign4(sizeof(dtPolyDetail)*params->polyCount);
const int detailVertsSize = dtAlign4(sizeof(float)*3*uniqueDetailVertCount);
const int detailTrisSize = dtAlign4(sizeof(unsigned char)*4*detailTriCount);
const int bvTreeSize = dtAlign4(sizeof(dtBVNode)*params->polyCount*2);
const int bvTreeSize = params->buildBvTree ? dtAlign4(sizeof(dtBVNode)*params->polyCount*2) : 0;
const int offMeshConsSize = dtAlign4(sizeof(dtOffMeshConnection)*storedOffMeshConCount);
const int dataSize = headerSize + vertsSize + polysSize + linksSize +
@@ -400,6 +437,7 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
header->version = DT_NAVMESH_VERSION;
header->x = params->tileX;
header->y = params->tileY;
header->layer = params->tileLayer;
header->userId = params->userId;
header->polyCount = totPolyCount;
header->vertCount = totVertCount;
@@ -415,7 +453,7 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
header->walkableRadius = params->walkableRadius;
header->walkableClimb = params->walkableClimb;
header->offMeshConCount = storedOffMeshConCount;
header->bvNodeCount = params->polyCount*2;
header->bvNodeCount = params->buildBvTree ? params->polyCount*2 : 0;
const int offMeshVertsBase = params->vertCount;
const int offMeshPolyBase = params->polyCount;
@@ -459,7 +497,27 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
{
if (src[j] == MESH_NULL_IDX) break;
p->verts[j] = src[j];
p->neis[j] = (src[nvp+j]+1) & 0xffff;
if (src[nvp+j] & 0x8000)
{
// Border or portal edge.
unsigned short dir = src[nvp+j] & 0xf;
if (dir == 0xf) // Border
p->neis[j] = 0;
else if (dir == 0) // Portal x-
p->neis[j] = DT_EXT_LINK | 4;
else if (dir == 1) // Portal z+
p->neis[j] = DT_EXT_LINK | 2;
else if (dir == 2) // Portal x+
p->neis[j] = DT_EXT_LINK | 0;
else if (dir == 3) // Portal z-
p->neis[j] = DT_EXT_LINK | 6;
}
else
{
// Normal connection
p->neis[j] = src[nvp+j]+1;
}
p->vertCount++;
}
src += nvp*2;
@@ -481,32 +539,6 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
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 = &params->verts[poly->verts[j]*3];
const unsigned short* vb = &params->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.
@@ -564,8 +596,11 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
// 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);
if (params->buildBvTree)
{
createBVTree(params->verts, params->vertCount, params->polys, params->polyCount,
nvp, params->cs, params->ch, params->polyCount*2, navBvtree);
}
// Store Off-Mesh connections.
n = 0;
@@ -597,51 +632,14 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
return true;
}
inline void swapByte(unsigned char* a, unsigned char* b)
{
unsigned char tmp = *a;
*a = *b;
*b = tmp;
}
inline void swapEndian(unsigned short* v)
{
unsigned char* x = (unsigned char*)v;
swapByte(x+0, x+1);
}
inline void swapEndian(short* v)
{
unsigned char* x = (unsigned char*)v;
swapByte(x+0, x+1);
}
inline void swapEndian(unsigned int* v)
{
unsigned char* x = (unsigned char*)v;
swapByte(x+0, x+3); swapByte(x+1, x+2);
}
inline void swapEndian(int* v)
{
unsigned char* x = (unsigned char*)v;
swapByte(x+0, x+3); swapByte(x+1, x+2);
}
inline void swapEndian(float* v)
{
unsigned char* x = (unsigned char*)v;
swapByte(x+0, x+3); swapByte(x+1, x+2);
}
bool dtNavMeshHeaderSwapEndian(unsigned char* data, const int /*dataSize*/)
{
dtMeshHeader* header = (dtMeshHeader*)data;
int swappedMagic = DT_NAVMESH_MAGIC;
int swappedVersion = DT_NAVMESH_VERSION;
swapEndian(&swappedMagic);
swapEndian(&swappedVersion);
dtSwapEndian(&swappedMagic);
dtSwapEndian(&swappedVersion);
if ((header->magic != DT_NAVMESH_MAGIC || header->version != DT_NAVMESH_VERSION) &&
(header->magic != swappedMagic || header->version != swappedVersion))
@@ -649,36 +647,43 @@ bool dtNavMeshHeaderSwapEndian(unsigned char* data, const int /*dataSize*/)
return false;
}
swapEndian(&header->magic);
swapEndian(&header->version);
swapEndian(&header->x);
swapEndian(&header->y);
swapEndian(&header->userId);
swapEndian(&header->polyCount);
swapEndian(&header->vertCount);
swapEndian(&header->maxLinkCount);
swapEndian(&header->detailMeshCount);
swapEndian(&header->detailVertCount);
swapEndian(&header->detailTriCount);
swapEndian(&header->bvNodeCount);
swapEndian(&header->offMeshConCount);
swapEndian(&header->offMeshBase);
swapEndian(&header->walkableHeight);
swapEndian(&header->walkableRadius);
swapEndian(&header->walkableClimb);
swapEndian(&header->bmin[0]);
swapEndian(&header->bmin[1]);
swapEndian(&header->bmin[2]);
swapEndian(&header->bmax[0]);
swapEndian(&header->bmax[1]);
swapEndian(&header->bmax[2]);
swapEndian(&header->bvQuantFactor);
dtSwapEndian(&header->magic);
dtSwapEndian(&header->version);
dtSwapEndian(&header->x);
dtSwapEndian(&header->y);
dtSwapEndian(&header->layer);
dtSwapEndian(&header->userId);
dtSwapEndian(&header->polyCount);
dtSwapEndian(&header->vertCount);
dtSwapEndian(&header->maxLinkCount);
dtSwapEndian(&header->detailMeshCount);
dtSwapEndian(&header->detailVertCount);
dtSwapEndian(&header->detailTriCount);
dtSwapEndian(&header->bvNodeCount);
dtSwapEndian(&header->offMeshConCount);
dtSwapEndian(&header->offMeshBase);
dtSwapEndian(&header->walkableHeight);
dtSwapEndian(&header->walkableRadius);
dtSwapEndian(&header->walkableClimb);
dtSwapEndian(&header->bmin[0]);
dtSwapEndian(&header->bmin[1]);
dtSwapEndian(&header->bmin[2]);
dtSwapEndian(&header->bmax[0]);
dtSwapEndian(&header->bmax[1]);
dtSwapEndian(&header->bmax[2]);
dtSwapEndian(&header->bvQuantFactor);
// Freelist index and pointers are updated when tile is added, no need to swap.
return true;
}
/// @par
///
/// @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.
bool dtNavMeshDataSwapEndian(unsigned char* data, const int /*dataSize*/)
{
// Make sure the data is in right format.
@@ -712,7 +717,7 @@ bool dtNavMeshDataSwapEndian(unsigned char* data, const int /*dataSize*/)
// Vertices
for (int i = 0; i < header->vertCount*3; ++i)
{
swapEndian(&verts[i]);
dtSwapEndian(&verts[i]);
}
// Polys
@@ -722,10 +727,10 @@ bool dtNavMeshDataSwapEndian(unsigned char* data, const int /*dataSize*/)
// poly->firstLink is update when tile is added, no need to swap.
for (int j = 0; j < DT_VERTS_PER_POLYGON; ++j)
{
swapEndian(&p->verts[j]);
swapEndian(&p->neis[j]);
dtSwapEndian(&p->verts[j]);
dtSwapEndian(&p->neis[j]);
}
swapEndian(&p->flags);
dtSwapEndian(&p->flags);
}
// Links are rebuild when tile is added, no need to swap.
@@ -734,14 +739,14 @@ bool dtNavMeshDataSwapEndian(unsigned char* data, const int /*dataSize*/)
for (int i = 0; i < header->detailMeshCount; ++i)
{
dtPolyDetail* pd = &detailMeshes[i];
swapEndian(&pd->vertBase);
swapEndian(&pd->triBase);
dtSwapEndian(&pd->vertBase);
dtSwapEndian(&pd->triBase);
}
// Detail verts
for (int i = 0; i < header->detailVertCount*3; ++i)
{
swapEndian(&detailVerts[i]);
dtSwapEndian(&detailVerts[i]);
}
// BV-tree
@@ -750,10 +755,10 @@ bool dtNavMeshDataSwapEndian(unsigned char* data, const int /*dataSize*/)
dtBVNode* node = &bvTree[i];
for (int j = 0; j < 3; ++j)
{
swapEndian(&node->bmin[j]);
swapEndian(&node->bmax[j]);
dtSwapEndian(&node->bmin[j]);
dtSwapEndian(&node->bmax[j]);
}
swapEndian(&node->i);
dtSwapEndian(&node->i);
}
// Off-mesh Connections.
@@ -761,9 +766,9 @@ bool dtNavMeshDataSwapEndian(unsigned char* data, const int /*dataSize*/)
{
dtOffMeshConnection* con = &offMeshCons[i];
for (int j = 0; j < 6; ++j)
swapEndian(&con->pos[j]);
swapEndian(&con->rad);
swapEndian(&con->poly);
dtSwapEndian(&con->pos[j]);
dtSwapEndian(&con->rad);
dtSwapEndian(&con->poly);
}
return true;

View File

@@ -24,6 +24,7 @@
inline unsigned int dtHashRef(dtPolyRef a)
{
// Edited by TC
a = (~a) + (a << 18);
a = a ^ (a >> 31);
a = a * 21;
@@ -70,27 +71,46 @@ void dtNodePool::clear()
m_nodeCount = 0;
}
dtNode* dtNodePool::findNode(dtPolyRef id)
unsigned int dtNodePool::findNodes(dtPolyRef id, dtNode** nodes, const int maxNodes)
{
int n = 0;
unsigned int bucket = dtHashRef(id) & (m_hashSize-1);
dtNodeIndex i = m_first[bucket];
while (i != DT_NULL_IDX)
{
if (m_nodes[i].id == id)
{
if (n >= maxNodes)
return n;
nodes[n++] = &m_nodes[i];
}
i = m_next[i];
}
return n;
}
dtNode* dtNodePool::findNode(dtPolyRef id, unsigned char state)
{
unsigned int bucket = dtHashRef(id) & (m_hashSize-1);
dtNodeIndex i = m_first[bucket];
while (i != DT_NULL_IDX)
{
if (m_nodes[i].id == id && m_nodes[i].state == state)
return &m_nodes[i];
i = m_next[i];
}
return 0;
}
dtNode* dtNodePool::getNode(dtPolyRef id)
dtNode* dtNodePool::getNode(dtPolyRef id, unsigned char state)
{
unsigned int bucket = dtHashRef(id) & (m_hashSize-1);
dtNodeIndex i = m_first[bucket];
dtNode* node = 0;
while (i != DT_NULL_IDX)
{
if (m_nodes[i].id == id)
if (m_nodes[i].id == id && m_nodes[i].state == state)
return &m_nodes[i];
i = m_next[i];
}
@@ -107,6 +127,7 @@ dtNode* dtNodePool::getNode(dtPolyRef id)
node->cost = 0;
node->total = 0;
node->id = id;
node->state = state;
node->flags = 0;
m_next[i] = m_first[bucket];

View File

@@ -33,7 +33,7 @@ set(collision_STAT_SRCS
include_directories(
${CMAKE_BINARY_DIR}
${CMAKE_SOURCE_DIR}/modules/worldengine/deps/g3dlite/include
${CMAKE_SOURCE_DIR}/modules/worldengine/deps/recastnavigation/Detour
${CMAKE_SOURCE_DIR}/modules/worldengine/deps/recastnavigation/Detour/Include
${CMAKE_SOURCE_DIR}/modules/worldengine/nucleus/src
${CMAKE_SOURCE_DIR}/modules/worldengine/nucleus/src/Configuration
${CMAKE_SOURCE_DIR}/modules/worldengine/nucleus/src/Debugging

View File

@@ -34,7 +34,7 @@ namespace VMAP
float iScale;
void init()
{
iRotation = G3D::Matrix3::fromEulerAnglesZYX(G3D::pi()*iDir.y/180.f, G3D::pi()*iDir.x/180.f, G3D::pi()*iDir.z/180.f);
iRotation = G3D::Matrix3::fromEulerAnglesZYX(G3D::pif()*iDir.y/180.f, G3D::pif()*iDir.x/180.f, G3D::pif()*iDir.z/180.f);
}
G3D::Vector3 transform(const G3D::Vector3& pIn) const;
void moveToBasePos(const G3D::Vector3& pBasePos) { iPos -= pBasePos; }

View File

@@ -0,0 +1,52 @@
/*
* Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
*
* 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 2 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/>.
*/
#ifndef __STRING_FORMAT_H__
#define __STRING_FORMAT_H__
#include <memory>
#include <iostream>
#include <string>
#include <cstdio>
namespace Trinity
{
/// Default TC string format function.
template<typename... Args>
inline std::string StringFormat(const std::string& format, Args const&... args)
{
size_t size = std::snprintf(nullptr, 0, format.c_str(), args ...) + 1; // Extra space for '\0'
unique_ptr<char[]> buf(new char[size]);
std::snprintf(buf.get(), size, format.c_str(), args ...);
return std::string(buf.get(), buf.get() + size - 1); // We don
}
/// Returns true if the given char pointer is null.
inline bool IsFormatEmptyOrNull(const char* fmt)
{
return fmt == nullptr;
}
/// Returns true if the given std::string is empty.
inline bool IsFormatEmptyOrNull(std::string const& fmt)
{
return fmt.empty();
}
}
#endif