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); }
/* 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; } }
/* 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; } }
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); } }