예제 #1
0
void TileSet::renderTile(uint id,
						 const Vec2d& position)
{
	if(id == 0) return;

	const TileInfo& tile = getTileInfo(id);
	if(tile.type == -1) return;

	glTexCoord2i(tile.position.x, tile.position.y);
	glVertex2d(position.x, position.y);

	glTexCoord2i(tile.position.x + tileSize.x, tile.position.y);
	glVertex2d(position.x + tileSize.x, position.y);

	glTexCoord2i(tile.position.x + tileSize.x, tile.position.y + tileSize.y);
	glVertex2d(position.x + tileSize.x, position.y + tileSize.y);

	glTexCoord2i(tile.position.x, tile.position.y + tileSize.y);
	glVertex2d(position.x, position.y + tileSize.y);
}
예제 #2
0
/*
	startpos:
	translate_dir: unit vector with only one of x, y or z
	face_dir: unit vector with only one of x, y or z
*/
static void updateFastFaceRow(
		MeshMakeData *data,
		v3s16 startpos,
		v3s16 translate_dir,
		v3f translate_dir_f,
		v3s16 face_dir,
		v3f face_dir_f,
		std::vector<FastFace> &dest)
{
	v3s16 p = startpos;
	
	u16 continuous_tiles_count = 0;
	
	bool makes_face = false;
	v3s16 p_corrected;
	v3s16 face_dir_corrected;
	u16 lights[4] = {0,0,0,0};
	TileSpec tile;
	u8 light_source = 0;
	getTileInfo(data, p, face_dir, 
			makes_face, p_corrected, face_dir_corrected,
			lights, tile, light_source);

	for(u16 j=0; j<MAP_BLOCKSIZE; j++)
	{
		// If tiling can be done, this is set to false in the next step
		bool next_is_different = true;
		
		v3s16 p_next;
		
		bool next_makes_face = false;
		v3s16 next_p_corrected;
		v3s16 next_face_dir_corrected;
		u16 next_lights[4] = {0,0,0,0};
		TileSpec next_tile;
		u8 next_light_source = 0;
		
		// If at last position, there is nothing to compare to and
		// the face must be drawn anyway
		if(j != MAP_BLOCKSIZE - 1)
		{
			p_next = p + translate_dir;
			
			getTileInfo(data, p_next, face_dir,
					next_makes_face, next_p_corrected,
					next_face_dir_corrected, next_lights,
					next_tile, next_light_source);
			
			if(next_makes_face == makes_face
					&& next_p_corrected == p_corrected + translate_dir
					&& next_face_dir_corrected == face_dir_corrected
					&& next_lights[0] == lights[0]
					&& next_lights[1] == lights[1]
					&& next_lights[2] == lights[2]
					&& next_lights[3] == lights[3]
					&& next_tile == tile
					&& tile.rotation == 0
					&& next_light_source == light_source)
			{
				next_is_different = false;
			}
			else{
				/*if(makes_face){
					g_profiler->add("Meshgen: diff: next_makes_face != makes_face",
							next_makes_face != makes_face ? 1 : 0);
					g_profiler->add("Meshgen: diff: n_p_corr != p_corr + t_dir",
							(next_p_corrected != p_corrected + translate_dir) ? 1 : 0);
					g_profiler->add("Meshgen: diff: next_f_dir_corr != f_dir_corr",
							next_face_dir_corrected != face_dir_corrected ? 1 : 0);
					g_profiler->add("Meshgen: diff: next_lights[] != lights[]",
							(next_lights[0] != lights[0] ||
							next_lights[0] != lights[0] ||
							next_lights[0] != lights[0] ||
							next_lights[0] != lights[0]) ? 1 : 0);
					g_profiler->add("Meshgen: diff: !(next_tile == tile)",
							!(next_tile == tile) ? 1 : 0);
				}*/
			}
			/*g_profiler->add("Meshgen: Total faces checked", 1);
			if(makes_face)
				g_profiler->add("Meshgen: Total makes_face checked", 1);*/
		} else {
			/*if(makes_face)
				g_profiler->add("Meshgen: diff: last position", 1);*/
		}

		continuous_tiles_count++;
		
		if(next_is_different)
		{
			/*
				Create a face if there should be one
			*/
			if(makes_face)
			{
				// Floating point conversion of the position vector
				v3f pf(p_corrected.X, p_corrected.Y, p_corrected.Z);
				// Center point of face (kind of)
				v3f sp = pf - ((f32)continuous_tiles_count / 2. - 0.5) * translate_dir_f;
				if(continuous_tiles_count != 1)
					sp += translate_dir_f;
				v3f scale(1,1,1);

				if(translate_dir.X != 0)
				{
					scale.X = continuous_tiles_count;
				}
				if(translate_dir.Y != 0)
				{
					scale.Y = continuous_tiles_count;
				}
				if(translate_dir.Z != 0)
				{
					scale.Z = continuous_tiles_count;
				}
				
				makeFastFace(tile, lights[0], lights[1], lights[2], lights[3],
						sp, face_dir_corrected, scale, light_source,
						dest);
				
				g_profiler->avg("Meshgen: faces drawn by tiling", 0);
				for(int i=1; i<continuous_tiles_count; i++){
					g_profiler->avg("Meshgen: faces drawn by tiling", 1);
				}
			}

			continuous_tiles_count = 0;
			
			makes_face = next_makes_face;
			p_corrected = next_p_corrected;
			face_dir_corrected = next_face_dir_corrected;
			lights[0] = next_lights[0];
			lights[1] = next_lights[1];
			lights[2] = next_lights[2];
			lights[3] = next_lights[3];
			tile = next_tile;
			light_source = next_light_source;
		}
		
		p = p_next;
	}
}
예제 #3
0
/*
	startpos:
	translate_dir: unit vector with only one of x, y or z
	face_dir: unit vector with only one of x, y or z
*/
void updateFastFaceRow(
		u32 daynight_ratio,
		v3f posRelative_f,
		v3s16 startpos,
		u16 length,
		v3s16 translate_dir,
		v3f translate_dir_f,
		v3s16 face_dir,
		v3f face_dir_f,
		core::array<FastFace> &dest,
		NodeModMap &temp_mods,
		VoxelManipulator &vmanip,
		v3s16 blockpos_nodes,
		bool smooth_lighting)
{
	v3s16 p = startpos;
	
	u16 continuous_tiles_count = 0;
	
	bool makes_face;
	v3s16 p_corrected;
	v3s16 face_dir_corrected;
	u8 lights[4];
	TileSpec tile;
	getTileInfo(blockpos_nodes, p, face_dir, daynight_ratio,
			vmanip, temp_mods, smooth_lighting,
			makes_face, p_corrected, face_dir_corrected, lights, tile);

	for(u16 j=0; j<length; j++)
	{
		// If tiling can be done, this is set to false in the next step
		bool next_is_different = true;
		
		v3s16 p_next;
		
		bool next_makes_face = false;
		v3s16 next_p_corrected;
		v3s16 next_face_dir_corrected;
		u8 next_lights[4] = {0,0,0,0};
		TileSpec next_tile;
		
		// If at last position, there is nothing to compare to and
		// the face must be drawn anyway
		if(j != length - 1)
		{
			p_next = p + translate_dir;
			
			getTileInfo(blockpos_nodes, p_next, face_dir, daynight_ratio,
					vmanip, temp_mods, smooth_lighting,
					next_makes_face, next_p_corrected,
					next_face_dir_corrected, next_lights,
					next_tile);
			
			if(next_makes_face == makes_face
					&& next_p_corrected == p_corrected
					&& next_face_dir_corrected == face_dir_corrected
					&& next_lights[0] == lights[0]
					&& next_lights[1] == lights[1]
					&& next_lights[2] == lights[2]
					&& next_lights[3] == lights[3]
					&& next_tile == tile)
			{
				next_is_different = false;
			}
		}

		continuous_tiles_count++;
		
		// This is set to true if the texture doesn't allow more tiling
		bool end_of_texture = false;
		/*
			If there is no texture, it can be tiled infinitely.
			If tiled==0, it means the texture can be tiled infinitely.
			Otherwise check tiled agains continuous_tiles_count.
		*/
		if(tile.texture.atlas != NULL && tile.texture.tiled != 0)
		{
			if(tile.texture.tiled <= continuous_tiles_count)
				end_of_texture = true;
		}
		
		// Do this to disable tiling textures
		//end_of_texture = true; //DEBUG
		
		if(next_is_different || end_of_texture)
		{
			/*
				Create a face if there should be one
			*/
			if(makes_face)
			{
				// Floating point conversion of the position vector
				v3f pf(p_corrected.X, p_corrected.Y, p_corrected.Z);
				// Center point of face (kind of)
				v3f sp = pf - ((f32)continuous_tiles_count / 2. - 0.5) * translate_dir_f;
				v3f scale(1,1,1);

				if(translate_dir.X != 0)
				{
					scale.X = continuous_tiles_count;
				}
				if(translate_dir.Y != 0)
				{
					scale.Y = continuous_tiles_count;
				}
				if(translate_dir.Z != 0)
				{
					scale.Z = continuous_tiles_count;
				}
				
				makeFastFace(tile, lights[0], lights[1], lights[2], lights[3],
						sp, face_dir_corrected, scale,
						posRelative_f, dest);
			}

			continuous_tiles_count = 0;
			
			makes_face = next_makes_face;
			p_corrected = next_p_corrected;
			face_dir_corrected = next_face_dir_corrected;
			lights[0] = next_lights[0];
			lights[1] = next_lights[1];
			lights[2] = next_lights[2];
			lights[3] = next_lights[3];
			tile = next_tile;
		}
		
		p = p_next;
	}
}
예제 #4
0
void CMapGenerator::createDirectConnections()
{
	for (auto connection : mapGenOptions->getMapTemplate()->getConnections())
	{
		auto zoneA = connection.getZoneA();
		auto zoneB = connection.getZoneB();

		//rearrange tiles in random order
		auto tilesCopy = zoneA->getTileInfo();
		std::vector<int3> tiles(tilesCopy.begin(), tilesCopy.end());

		int3 guardPos(-1,-1,-1);

		auto otherZoneTiles = zoneB->getTileInfo();

		int3 posA = zoneA->getPos();
		int3 posB = zoneB->getPos();
		// auto zoneAid = zoneA->getId();
		auto zoneBid = zoneB->getId();

		if (posA.z == posB.z)
		{
			std::vector<int3> middleTiles;
			for (auto tile : tilesCopy)
			{
				if (isBlocked(tile)) //tiles may be occupied by subterranean gates already placed
					continue;
				foreachDirectNeighbour (tile, [&guardPos, tile, &otherZoneTiles, &middleTiles, this, zoneBid](int3 &pos) //must be direct since paths also also generated between direct neighbours
				{
					if (getZoneID(pos) == zoneBid)
						middleTiles.push_back(tile);
				});
			}

			//find tiles with minimum manhattan distance from center of the mass of zone border
			size_t tilesCount = middleTiles.size() ? middleTiles.size() : 1;
			int3 middleTile = std::accumulate(middleTiles.begin(), middleTiles.end(), int3(0, 0, 0));
			middleTile.x /= tilesCount;
			middleTile.y /= tilesCount;
			middleTile.z /= tilesCount; //TODO: implement division operator for int3?
			boost::sort(middleTiles, [middleTile](const int3 &lhs, const int3 &rhs) -> bool
			{
				//choose tiles with both corrdinates in the middle
				return lhs.mandist2d(middleTile) < rhs.mandist2d(middleTile);
			});

			//remove 1/4 tiles from each side - path should cross zone borders at smooth angle
			size_t removedCount = tilesCount / 4; //rounded down
			middleTiles.erase(middleTiles.end() - removedCount, middleTiles.end());
			middleTiles.erase(middleTiles.begin(), middleTiles.begin() + removedCount);

			RandomGeneratorUtil::randomShuffle(middleTiles, rand);
			for (auto tile : middleTiles)
			{
				guardPos = tile;
				if (guardPos.valid())
				{
					setOccupied(guardPos, ETileType::FREE); //just in case monster is too weak to spawn
					zoneA->addMonster(this, guardPos, connection.getGuardStrength(), false, true);
					//zones can make paths only in their own area
					zoneA->crunchPath(this, guardPos, posA, true, zoneA->getFreePaths()); //make connection towards our zone center
					zoneB->crunchPath(this, guardPos, posB, true, zoneB->getFreePaths()); //make connection towards other zone center

					zoneA->addRoadNode(guardPos);
					zoneB->addRoadNode(guardPos);
					break; //we're done with this connection
				}
			}
		}

		if (!guardPos.valid())
			connectionsLeft.push_back(connection);
	}
}