예제 #1
0
파일: world.cpp 프로젝트: gfoekfi/warzeub2
void World::GenerateAccessibleTileSurface(EUnitType parUnitType)
{
	if (unitTypeToAccessibleSurface.count(parUnitType) > 0)
		SDL_FreeSurface(unitTypeToAccessibleSurface[parUnitType]);

	unitTypeToAccessibleSurface[parUnitType] = SDL_CreateRGBSurface(SDL_HWSURFACE,
		width_ * BUILD_TILE_SIZE, height_ * BUILD_TILE_SIZE,
		screen->format->BitsPerPixel,
		screen->format->Rmask, screen->format->Gmask,
		screen->format->Bmask, screen->format->Amask);
	assert(unitTypeToAccessibleSurface[parUnitType]);

	SDL_Rect dst = { 0, 0, BUILD_TILE_SIZE, BUILD_TILE_SIZE };
	int2 unitDimension(unitTypeToUnitDesc[parUnitType].width, unitTypeToUnitDesc[parUnitType].height);
	for (size_t x = 0; x < width_; ++x)
		for (size_t y = 0; y < height_; ++y)
		{
			if (!IsBuildTileAccessible(BuildTile(x, y), unitDimension))
			{
				dst.x = x * BUILD_TILE_SIZE;
				dst.y = y * BUILD_TILE_SIZE;
				SDL_FillRect(unitTypeToAccessibleSurface[parUnitType], &dst, 0x00ff0000);
			}
			else
			{
				SDL_Rect buildTileRect = { x * BUILD_TILE_SIZE, y * BUILD_TILE_SIZE, BUILD_TILE_SIZE, BUILD_TILE_SIZE};
				SDL_FillRect(unitTypeToAccessibleSurface[parUnitType], &buildTileRect, ((x + y) % 2) ? 0x000000ff : 0x00ffffff);
			}
		}
}
예제 #2
0
bool NavigationMesh::Build(const BoundingBox& boundingBox)
{
    PROFILE(BuildPartialNavigationMesh);
    
    if (!node_)
        return false;
    
    if (!navMesh_)
    {
        LOGERROR("Navigation mesh must first be built fully before it can be partially rebuilt");
        return false;
    }
    
    if (!node_->GetWorldScale().Equals(Vector3::ONE))
        LOGWARNING("Navigation mesh root node has scaling. Agent parameters may not work as intended");
    
    BoundingBox localSpaceBox = boundingBox.Transformed(node_->GetWorldTransform().Inverse());
    
    float tileEdgeLength = (float)tileSize_ * cellSize_;
    
    Vector<NavigationGeometryInfo> geometryList;
    CollectGeometries(geometryList);
    
    int sx = Clamp((int)((localSpaceBox.min_.x_ - boundingBox_.min_.x_) / tileEdgeLength), 0, numTilesX_ - 1);
    int sz = Clamp((int)((localSpaceBox.min_.z_ - boundingBox_.min_.z_) / tileEdgeLength), 0, numTilesZ_ - 1);
    int ex = Clamp((int)((localSpaceBox.max_.x_ - boundingBox_.min_.x_) / tileEdgeLength), 0, numTilesX_ - 1);
    int ez = Clamp((int)((localSpaceBox.max_.z_ - boundingBox_.min_.z_) / tileEdgeLength), 0, numTilesZ_ - 1);
    
    unsigned numTiles = 0;
    
    for (int z = sz; z <= ez; ++z)
    {
        for (int x = sx; x <= ex; ++x)
        {
            if (BuildTile(geometryList, x, z))
                ++numTiles;
        }
    }
    
    LOGDEBUG("Rebuilt " + String(numTiles) + " tiles of the navigation mesh");
    return true;
}
예제 #3
0
bool NavigationMesh::Build()
{
    PROFILE(BuildNavigationMesh);
    
    // Release existing navigation data and zero the bounding box
    ReleaseNavigationMesh();
    
    if (!node_)
        return false;
    
    if (!node_->GetWorldScale().Equals(Vector3::ONE))
        LOGWARNING("Navigation mesh root node has scaling. Agent parameters may not work as intended");
    
    Vector<NavigationGeometryInfo> geometryList;
    CollectGeometries(geometryList);
    
    if (geometryList.Empty())
        return true; // Nothing to do
    
    // Build the combined bounding box
    for (unsigned i = 0; i < geometryList.Size(); ++i)
        boundingBox_.Merge(geometryList[i].boundingBox_);
    
    // Expand bounding box by padding
    boundingBox_.min_ -= padding_;
    boundingBox_.max_ += padding_;
    
    {
        PROFILE(BuildNavigationMesh);
        
        // Calculate number of tiles
        int gridW = 0, gridH = 0;
        float tileEdgeLength = (float)tileSize_ * cellSize_;
        rcCalcGridSize(&boundingBox_.min_.x_, &boundingBox_.max_.x_, cellSize_, &gridW, &gridH);
        numTilesX_ = (gridW + tileSize_ - 1) / tileSize_;
        numTilesZ_ = (gridH + tileSize_ - 1) / tileSize_;
        
        // Calculate max. number of tiles and polygons, 22 bits available to identify both tile & polygon within tile
        unsigned maxTiles = NextPowerOfTwo(numTilesX_ * numTilesZ_);
        unsigned tileBits = 0;
        unsigned temp = maxTiles;
        while (temp > 1)
        {
            temp >>= 1;
            ++tileBits;
        }
        
        unsigned maxPolys = 1 << (22 - tileBits);
        
        dtNavMeshParams params;
        rcVcopy(params.orig, &boundingBox_.min_.x_);
        params.tileWidth = tileEdgeLength;
        params.tileHeight = tileEdgeLength;
        params.maxTiles = maxTiles;
        params.maxPolys = maxPolys;
        
        navMesh_ = dtAllocNavMesh();
        if (!navMesh_)
        {
            LOGERROR("Could not allocate navigation mesh");
            return false;
        }
        
        if (dtStatusFailed(navMesh_->init(&params)))
        {
            LOGERROR("Could not initialize navigation mesh");
            ReleaseNavigationMesh();
            return false;
        }
        
        // Build each tile
        unsigned numTiles = 0;
        
        for (int z = 0; z < numTilesZ_; ++z)
        {
            for (int x = 0; x < numTilesX_; ++x)
            {
                if (BuildTile(geometryList, x, z))
                    ++numTiles;
            }
        }
        
        LOGDEBUG("Built navigation mesh with " + String(numTiles) + " tiles");
        return true;
    }
}