Example #1
0
    NavMeshPtr makeEmptyNavMesh(const Settings& settings)
    {
        // Max tiles and max polys affect how the tile IDs are caculated.
        // There are 22 bits available for identifying a tile and a polygon.
        const int polysAndTilesBits = 22;
        const auto polysBits = getMinValuableBitsNumber(settings.mMaxPolys);

        if (polysBits >= polysAndTilesBits)
            throw InvalidArgument("Too many polygons per tile");

        const auto tilesBits = polysAndTilesBits - polysBits;

        dtNavMeshParams params;
        std::fill_n(params.orig, 3, 0.0f);
        params.tileWidth = settings.mTileSize * settings.mCellSize;
        params.tileHeight = settings.mTileSize * settings.mCellSize;
        params.maxTiles = 1 << tilesBits;
        params.maxPolys = 1 << polysBits;

        NavMeshPtr navMesh(dtAllocNavMesh(), &dtFreeNavMesh);
        const auto status = navMesh->init(&params);

        if (!dtStatusSucceed(status))
            throw NavigatorException("Failed to init navmesh");

        return navMesh;
    }
NavMeshLoader::LoadResult NavMeshLoader::LoadZoneMeshData(const std::shared_ptr<char>& data, DWORD length)
{
	ReadCursor cursor{ data.get(), length };

	//------------------------------------------------------------------------
	// Read the header
	NavMeshSetHeader header;
	if (!FillStructure(cursor, header)) {
		DebugSpewAlways("Failed to read header from mesh file!");
		return CORRUPT;
	}

	if (header.magic != NAVMESHSET_MAGIC) {
		DebugSpewAlways("Header Magic value mismatch!");
		return CORRUPT;
	}
	if (header.version != NAVMESHSET_VERSION) {
		DebugSpewAlways("Header version mismatch!");
		return VERSION_MISMATCH;
	}

	std::unique_ptr<dtNavMesh> navMesh(new dtNavMesh);
	if (!navMesh->init(&header.params)) {
		DebugSpewAlways("Header params are bad!");
		return CORRUPT;
	}

	//------------------------------------------------------------------------
	// Read the tiles
	int passtile = 0, failtile = 0;

	for (int i = 0; i < header.numTiles; ++i)
	{
		NavMeshTileHeader tileHeader;
		if (!FillStructure(cursor, tileHeader)) {
			DebugSpewAlways("Failed to read tile header for tile %d!", i);
			return CORRUPT;
		}

		if (!tileHeader.tileRef || !tileHeader.dataSize) {
			continue;
		}

		// validate the size. For sure it should not exceed the remainder of the
		// file size.
		if (tileHeader.dataSize < 0 || tileHeader.dataSize > cursor.length) {
			DebugSpewAlways("tileHeader's dataSize has invalid size %d for tile %d",
				tileHeader.dataSize, i);
			return CORRUPT;
		}

		unsigned char* tileData = (unsigned char*)dtAlloc(tileHeader.dataSize, DT_ALLOC_PERM);
		memcpy(tileData, cursor.data, tileHeader.dataSize);
		cursor.length -= tileHeader.dataSize;
		cursor.data += tileHeader.dataSize;

		if (navMesh->addTile(tileData, tileHeader.dataSize, DT_TILE_FREE_DATA, tileHeader.tileRef, 0))
			passtile++;
		else
		{
			DebugSpewAlways("Failed to load tile %d", i);
			failtile++;
		}
	}

	// these values shouldn't be set until we have a successful load
	m_loadedTiles = passtile;
	m_mesh = std::move(navMesh);
	OnNavMeshChanged(m_mesh.get());

	return SUCCESS;
}