Exemplo n.º 1
0
void ContinentBuilder::Build(bool debug)
{
    char buff[50];
    sprintf(buff, "mmaps/%03u.mmap", MapId);
    FILE* mmap = fopen(buff, "wb");
    if (!mmap)
    {
        printf("Could not create file %s. Check that you have write permissions to the destination folder and try again\n", buff);
        return;
    }

    CalculateTileBounds();

    dtNavMeshParams params;
    params.maxPolys = 1 << STATIC_POLY_BITS;
    params.maxTiles = TileMap->TileTable.size();
    rcVcopy(params.orig, bmin);
    params.tileHeight = Constants::TileSize;
    params.tileWidth = Constants::TileSize;
    fwrite(&params, sizeof(dtNavMeshParams), 1, mmap);
    fclose(mmap);
    std::vector<BuilderThread*> Threads;
    for (uint32 i = 0; i < NumberOfThreads; ++i)
        Threads.push_back(new BuilderThread(this, debug, params));
    printf("Map %s ( %u ) has %u tiles. Building them with %u threads\n", Continent.c_str(), MapId, uint32(TileMap->TileTable.size()), NumberOfThreads);
    for (std::vector<TilePos>::iterator itr = TileMap->TileTable.begin(); itr != TileMap->TileTable.end(); ++itr)
    {
        bool next = false;
        while (!next)
        {
            for (std::vector<BuilderThread*>::iterator _th = Threads.begin(); _th != Threads.end(); ++_th)
            {
                if ((*_th)->Free)
                {
                    (*_th)->SetData(itr->X, itr->Y, MapId, Continent);
                    (*_th)->activate();
                    next = true;
                    break;
                }
            }
            // Wait for 20 seconds
            ACE_OS::sleep(ACE_Time_Value (0, 20000));
        }
    }
    Cache->Clear();

    // Free memory
    for (std::vector<BuilderThread*>::iterator _th = Threads.begin(); _th != Threads.end(); ++_th)
    {
        (*_th)->wait();
        delete *_th;
    }
}
Exemplo n.º 2
0
uint8* TileBuilder::BuildTiled(dtNavMeshParams& navMeshParams)
{
    _Geometry = new Geometry();
    _Geometry->Transform = true;
    ADT* adt = new ADT(Utils::GetAdtPath(World, X, Y), X, Y);
    adt->Read();
    _Geometry->AddAdt(adt);
    delete adt;

    if (_Geometry->Vertices.empty() && _Geometry->Triangles.empty())
        return NULL;

    float* bmin = NULL, *bmax = NULL;
    CalculateTileBounds(bmin, bmax, navMeshParams);
    _Geometry->CalculateMinMaxHeight(bmin[1], bmax[1]);

    // again, we load everything - wasteful but who cares
    for (int ty = Y - 1; ty <= Y + 1; ty++)
    {
        for (int tx = X - 1; tx <= X + 1; tx++)
        {
            // don't load main tile again
            if (tx == X && ty == Y)
                continue;

            ADT* _adt = new ADT(Utils::GetAdtPath(World, tx, ty), tx, ty);
            // If this condition is met, it means that this WDT does not contain the ADT
            if (!_adt->Data->Stream)
            {
                delete _adt;
                continue;
            }
            _adt->Read();
            _Geometry->AddAdt(_adt);
            delete _adt;
        }
    }

    OutputDebugVertices();
    
    uint32 numVerts = _Geometry->Vertices.size();
    uint32 numTris = _Geometry->Triangles.size();
    float* vertices;
    int* triangles;
    uint8* areas;
    _Geometry->GetRawData(vertices, triangles, areas);
    _Geometry->Vertices.clear();
    _Geometry->Triangles.clear();

    // add border
    bmin[0] -= Config.borderSize * Config.cs;
    bmin[2] -= Config.borderSize * Config.cs;
    bmax[0] += Config.borderSize * Config.cs;
    bmax[2] += Config.borderSize * Config.cs;

    rcHeightfield* hf = rcAllocHeightfield();
    int width = Config.tileSize + (Config.borderSize * 2);
    rcCreateHeightfield(Context, *hf, width, width, bmin, bmax, Config.cs, Config.ch);

    rcClearUnwalkableTriangles(Context, Config.walkableSlopeAngle, vertices, numVerts, triangles, numTris, areas);
    rcRasterizeTriangles(Context, vertices, numVerts, triangles, areas, numTris, *hf, Config.walkableClimb);

    rcFilterLowHangingWalkableObstacles(Context, Config.walkableClimb, *hf);
    rcFilterLedgeSpans(Context, Config.walkableHeight, Config.walkableClimb, *hf);
    rcFilterWalkableLowHeightSpans(Context, Config.walkableHeight, *hf);

    rcCompactHeightfield* chf = rcAllocCompactHeightfield();
    rcBuildCompactHeightfield(Context, Config.walkableHeight, Config.walkableClimb, *hf, *chf);

    rcErodeWalkableArea(Context, Config.walkableRadius, *chf);
    rcBuildDistanceField(Context, *chf);
    rcBuildRegions(Context, *chf, Config.borderSize, Config.minRegionArea, Config.mergeRegionArea);

    rcContourSet* contours = rcAllocContourSet();
    rcBuildContours(Context, *chf, Config.maxSimplificationError, Config.maxEdgeLen, *contours);

    rcPolyMesh* pmesh = rcAllocPolyMesh();
    rcBuildPolyMesh(Context, *contours, Config.maxVertsPerPoly, *pmesh);

    rcPolyMeshDetail* dmesh = rcAllocPolyMeshDetail();
    rcBuildPolyMeshDetail(Context, *pmesh, *chf, Config.detailSampleDist, Config.detailSampleMaxError, *dmesh);

    // Set flags according to area types (e.g. Swim for Water)
    for (int i = 0; i < pmesh->npolys; i++)
    {
        if (pmesh->areas[i] == Constants::POLY_AREA_ROAD || pmesh->areas[i] == Constants::POLY_AREA_TERRAIN)
            pmesh->flags[i] = Constants::POLY_FLAG_WALK;
        else if (pmesh->areas[i] == Constants::POLY_AREA_WATER)
            pmesh->flags[i] = Constants::POLY_FLAG_SWIM;
    }

    dtNavMeshCreateParams params;
    memset(&params, 0, sizeof(params));
    // PolyMesh data
    params.verts = pmesh->verts;
    params.vertCount = pmesh->nverts;
    params.polys = pmesh->polys;
    params.polyAreas = pmesh->areas;
    params.polyFlags = pmesh->flags;
    params.polyCount = pmesh->npolys;
    params.nvp = pmesh->nvp;
    // PolyMeshDetail data
    params.detailMeshes = dmesh->meshes;
    params.detailVerts = dmesh->verts;
    params.detailVertsCount = dmesh->nverts;
    params.detailTris = dmesh->tris;
    params.detailTriCount = dmesh->ntris;
    // General settings
    params.ch = Config.ch;
    params.cs = Config.cs;
    params.walkableClimb = Config.walkableClimb * Config.ch;
    params.walkableHeight = Config.walkableHeight * Config.ch;
    params.walkableRadius = Config.walkableRadius * Config.cs;
    params.tileX = X;
    params.tileY = Y;
    params.tileLayer = 0;
    params.buildBvTree = true;

    // Recalculate the bounds with the added geometry
    float* bmin2 = NULL, *bmax2 = NULL;
    CalculateTileBounds(bmin2, bmax2, navMeshParams);
    bmin2[1] = bmin[1];
    bmax2[1] = bmax[1];

    rcVcopy(params.bmax, bmax2);
    rcVcopy(params.bmin, bmin2);

    // Offmesh-connection settings
    params.offMeshConCount = 0; // none for now

    rcFreeHeightField(hf);
    rcFreeCompactHeightfield(chf);
    rcFreeContourSet(contours);
    delete vertices;
    delete triangles;
    delete areas;
    delete bmin;
    delete bmax;

    if (!params.polyCount || !params.polys || Constants::TilesPerMap * Constants::TilesPerMap == params.polyCount)
    {
        // we have flat tiles with no actual geometry - don't build those, its useless
        // keep in mind that we do output those into debug info
        // drop tiles with only exact count - some tiles may have geometry while having less tiles
        printf("[%02i, %02i] No polygons to build on tile, skipping.\n", X, Y);
        rcFreePolyMesh(pmesh);
        rcFreePolyMeshDetail(dmesh);
        return NULL;
    }

    int navDataSize;
    uint8* navData;
    printf("[%02i, %02i] Creating the navmesh with %i vertices, %i polys, %i triangles!\n", X, Y, params.vertCount, params.polyCount, params.detailTriCount);
    bool result = dtCreateNavMeshData(&params, &navData, &navDataSize);

    rcFreePolyMesh(pmesh);
    rcFreePolyMeshDetail(dmesh);

    if (result)
    {
        printf("[%02i, %02i] NavMesh created, size %i!\n", X, Y, navDataSize);
        DataSize = navDataSize;
        return navData;
    }

    return NULL;
}
Exemplo n.º 3
0
void ContinentBuilder::Build()
{
    char buff[50];
    sprintf(buff, "mmaps/%03u.mmap", MapId);
    FILE* mmap = fopen(buff, "wb");
    if (!mmap)
    {
        printf("Could not create file %s. Check that you have write permissions to the destination folder and try again\n", buff);
        return;
    }

    CalculateTileBounds();

    dtNavMeshParams params;
    
    std::vector<BuilderThread*> Threads;

    if (TileMap->IsGlobalModel)
    {
        printf("Map %s ( %u ) is a WMO. Building with 1 thread.\n", Continent.c_str(), MapId);
        
        TileBuilder* builder = new TileBuilder(this, Continent, 0, 0, MapId);
        builder->AddGeometry(TileMap->Model, TileMap->ModelDefinition);
        uint8* nav = builder->BuildInstance(params);
        if (nav)
        {
            // Set some params for the navmesh
            dtMeshHeader* header = (dtMeshHeader*)nav;
            dtVcopy(params.orig, header->bmin);
            params.tileWidth = header->bmax[0] - header->bmin[0];
            params.tileHeight = header->bmax[2] - header->bmin[2];
            params.maxTiles = 1;
            params.maxPolys = header->polyCount;
            fwrite(&params, sizeof(dtNavMeshParams), 1, mmap);
            fclose(mmap);

            char buff[100];
            sprintf(buff, "mmaps/%03u%02i%02i.mmtile", MapId, 0, 0);
            FILE* f = fopen(buff, "wb");
            if (!f)
            {
                printf("Could not create file %s. Check that you have write permissions to the destination folder and try again\n", buff);
                return;
            }

            MmapTileHeader mheader;
            mheader.size = builder->DataSize;
            fwrite(&mheader, sizeof(MmapTileHeader), 1, f);
            fwrite(nav, sizeof(unsigned char), builder->DataSize, f);
            fclose(f);
        }

        dtFree(nav);
        delete builder;
    }
    else
    {
        params.maxPolys = 32768;
        params.maxTiles = 4096;
        rcVcopy(params.orig, Constants::Origin);
        params.tileHeight = Constants::TileSize;
        params.tileWidth = Constants::TileSize;
        fwrite(&params, sizeof(dtNavMeshParams), 1, mmap);
        fclose(mmap);

        for (uint32 i = 0; i < NumberOfThreads; ++i)
            Threads.push_back(new BuilderThread(this, params));
        printf("Map %s ( %u ) has %u tiles. Building them with %u threads\n", Continent.c_str(), MapId, uint32(TileMap->TileTable.size()), NumberOfThreads);
        for (std::vector<TilePos>::iterator itr = TileMap->TileTable.begin(); itr != TileMap->TileTable.end(); ++itr)
        {
            bool next = false;
            while (!next)
            {
                for (std::vector<BuilderThread*>::iterator _th = Threads.begin(); _th != Threads.end(); ++_th)
                {
                    if ((*_th)->Free)
                    {
                        (*_th)->SetData(itr->X, itr->Y, MapId, Continent);
                        (*_th)->activate();
                        next = true;
                        break;
                    }
                }
                // Wait for 20 seconds
                ACE_OS::sleep(ACE_Time_Value (0, 20000));
            }
        }
    }

    Cache->Clear();

    // Free memory
    for (std::vector<BuilderThread*>::iterator _th = Threads.begin(); _th != Threads.end(); ++_th)
    {
        (*_th)->wait();
        delete *_th;
    }
}