void cCaveTunnel::Randomize(cNoise & a_Noise) { // Repeat 4 times: for (int i = 0; i < 4; i++) { // For each already present point, insert a point in between it and its predecessor, shifted randomly. int PrevX = m_Points.front().m_BlockX; int PrevY = m_Points.front().m_BlockY; int PrevZ = m_Points.front().m_BlockZ; int PrevR = m_Points.front().m_Radius; cCaveDefPoints Pts; Pts.reserve(m_Points.size() * 2 + 1); Pts.push_back(m_Points.front()); for (cCaveDefPoints::const_iterator itr = m_Points.begin() + 1, end = m_Points.end(); itr != end; ++itr) { int Random = a_Noise.IntNoise3DInt(PrevX, PrevY, PrevZ + i) / 11; int len = (PrevX - itr->m_BlockX) * (PrevX - itr->m_BlockX); len += (PrevY - itr->m_BlockY) * (PrevY - itr->m_BlockY); len += (PrevZ - itr->m_BlockZ) * (PrevZ - itr->m_BlockZ); len = 3 * (int)sqrt((double)len) / 4; int Rad = std::min(MAX_RADIUS, std::max(MIN_RADIUS, (PrevR + itr->m_Radius) / 2 + (Random % 3) - 1)); Random /= 4; int x = (itr->m_BlockX + PrevX) / 2 + (Random % (len + 1) - len / 2); Random /= 256; int y = (itr->m_BlockY + PrevY) / 2 + (Random % (len / 2 + 1) - len / 4); Random /= 256; int z = (itr->m_BlockZ + PrevZ) / 2 + (Random % (len + 1) - len / 2); Pts.push_back(cCaveDefPoint(x, y, z, Rad)); Pts.push_back(*itr); PrevX = itr->m_BlockX; PrevY = itr->m_BlockY; PrevZ = itr->m_BlockZ; PrevR = itr->m_Radius; } std::swap(Pts, m_Points); } }
void cCaveTunnel::FinishLinear(void) { // For each segment, use Bresenham's 3D line algorithm to draw a "line" of defpoints cCaveDefPoints Pts; std::swap(Pts, m_Points); m_Points.reserve(Pts.size() * 3); cCaveDefPoint & PrevPoint = Pts.front(); int PrevX = PrevPoint.m_BlockX; int PrevY = PrevPoint.m_BlockY; int PrevZ = PrevPoint.m_BlockZ; for (cCaveDefPoints::const_iterator itr = Pts.begin() + 1, end = Pts.end(); itr != end; ++itr) { int x1 = itr->m_BlockX; int y1 = itr->m_BlockY; int z1 = itr->m_BlockZ; int dx = abs(x1 - PrevX); int dy = abs(y1 - PrevY); int dz = abs(z1 - PrevZ); int sx = (PrevX < x1) ? 1 : -1; int sy = (PrevY < y1) ? 1 : -1; int sz = (PrevZ < z1) ? 1 : -1; int R = itr->m_Radius; if (dx >= std::max(dy, dz)) // x dominant { int yd = dy - dx / 2; int zd = dz - dx / 2; for (;;) { m_Points.push_back(cCaveDefPoint(PrevX, PrevY, PrevZ, R)); if (PrevX == x1) { break; } if (yd >= 0) // move along y { PrevY += sy; yd -= dx; } if (zd >= 0) // move along z { PrevZ += sz; zd -= dx; } // move along x PrevX += sx; yd += dy; zd += dz; } } else if (dy >= std::max(dx, dz)) // y dominant { int xd = dx - dy / 2; int zd = dz - dy / 2; for (;;) { m_Points.push_back(cCaveDefPoint(PrevX, PrevY, PrevZ, R)); if (PrevY == y1) { break; } if (xd >= 0) // move along x { PrevX += sx; xd -= dy; } if (zd >= 0) // move along z { PrevZ += sz; zd -= dy; } // move along y PrevY += sy; xd += dx; zd += dz; } } else { // z dominant ASSERT(dz >= std::max(dx, dy)); int xd = dx - dz / 2; int yd = dy - dz / 2; for (;;) { m_Points.push_back(cCaveDefPoint(PrevX, PrevY, PrevZ, R)); if (PrevZ == z1) { break; } if (xd >= 0) // move along x { PrevX += sx; xd -= dz; } if (yd >= 0) // move along y { PrevY += sy; yd -= dz; } // move along z PrevZ += sz; xd += dx; yd += dy; } } // if (which dimension is dominant) } // for itr }