Пример #1
0
bool cCaveTunnel::RefineDefPoints(const cCaveDefPoints & a_Src, cCaveDefPoints & a_Dst)
{
	if (a_Src.size() < 2)
	{
		// There are no midpoints, nothing to smooth
		return true;
	}

	// Smoothing: for each line segment, add points on its 1 / 4 lengths
	bool res = false;
	size_t Num = a_Src.size() - 2;  // this many intermediary points
	a_Dst.clear();
	a_Dst.reserve(Num * 2 + 2);
	cCaveDefPoints::const_iterator itr = a_Src.begin() + 1;
	const cCaveDefPoint & Source = a_Src.front();
	a_Dst.push_back(Source);
	int PrevX = Source.m_BlockX;
	int PrevY = Source.m_BlockY;
	int PrevZ = Source.m_BlockZ;
	int PrevR = Source.m_Radius;
	for (size_t i = 0; i <= Num; ++i, ++itr)
	{
		int dx = itr->m_BlockX - PrevX;
		int dy = itr->m_BlockY - PrevY;
		int dz = itr->m_BlockZ - PrevZ;
		if (abs(dx) + abs(dz) + abs(dy) < 6)
		{
			// Too short a segment to smooth-subdivide into quarters
			PrevX = itr->m_BlockX;
			PrevY = itr->m_BlockY;
			PrevZ = itr->m_BlockZ;
			PrevR = itr->m_Radius;
			continue;
		}
		int dr = itr->m_Radius - PrevR;
		int Rad1 = std::max(PrevR + 1 * dr / 4, 1);
		int Rad2 = std::max(PrevR + 3 * dr / 4, 1);
		a_Dst.push_back(cCaveDefPoint(PrevX + 1 * dx / 4, PrevY + 1 * dy / 4, PrevZ + 1 * dz / 4, Rad1));
		a_Dst.push_back(cCaveDefPoint(PrevX + 3 * dx / 4, PrevY + 3 * dy / 4, PrevZ + 3 * dz / 4, Rad2));
		PrevX = itr->m_BlockX;
		PrevY = itr->m_BlockY;
		PrevZ = itr->m_BlockZ;
		PrevR = itr->m_Radius;
		res = true;
	}
	a_Dst.push_back(a_Src.back());
	return res && (a_Src.size() < a_Dst.size());
}
Пример #2
0
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
}