예제 #1
0
// ---------------------------------------------------------------------
// Create an approximate mesh.
//
bool Patch::Tessellate(const float3& campos, int groundDetail)
{
	// Set/Update LOD params (FIXME: wrong height?)
	const float myx = (coors.x + PATCH_SIZE / 2) * SQUARE_SIZE;
	const float myz = (coors.y + PATCH_SIZE / 2) * SQUARE_SIZE;
	const float myy = (readMap->GetCurrMinHeight() + readMap->GetCurrMaxHeight()) * 0.5f;
	const float3 myPos(myx, myy, myz);

	camDistLODFactor  = myPos.distance(campos);
	camDistLODFactor *= 300.0f / groundDetail; // MAGIC NUMBER 1: increase the dividend to reduce LOD in camera distance
	camDistLODFactor  = std::max(1.0f, camDistLODFactor);
	camDistLODFactor  = 1.0f / camDistLODFactor;

	// MAGIC NUMBER 2:
	//   variances are clamped by it, so it regulates how strong areas are tessellated.
	//   Note, the maximum tessellation is untouched by it. Instead it reduces the maximum
	//   LOD in distance, while the param above defines the overall FallOff rate.
	varianceMaxLimit = groundDetail * 0.35f;

	{
		// Split each of the base triangles
		currentVariance = &varianceLeft[0];

		const int2 left = {coors.x,              coors.y + PATCH_SIZE};
		const int2 rght = {coors.x + PATCH_SIZE, coors.y             };
		const int2 apex = {coors.x,              coors.y             };

		RecursTessellate(&baseLeft, left, rght, apex, 1);
	}
	{
		currentVariance = &varianceRight[0];

		const int2 left = {coors.x + PATCH_SIZE, coors.y             };
		const int2 rght = {coors.x,              coors.y + PATCH_SIZE};
		const int2 apex = {coors.x + PATCH_SIZE, coors.y + PATCH_SIZE};

		RecursTessellate(&baseRight, left, rght, apex, 1);
	}

	return (!CTriNodePool::GetPool()->OutOfNodes());
}
예제 #2
0
// ---------------------------------------------------------------------
// Tessellate a Patch.
// Will continue to split until the variance metric is met.
//
void Patch::RecursTessellate(TriTreeNode* tri, const int2 left, const int2 right, const int2 apex, const int node)
{
	// bail if we can not tessellate further in at least one dimension
	if ((abs(left.x - right.x) <= 1) && (abs(left.y - right.y) <= 1))
		return;

	// default > 1; when variance isn't saved this issues further tessellation
	float TriVariance = 10.0f;

	if (node < (1 << VARIANCE_DEPTH)) {
		// make max tessellation viewRadius dependent
		// w/o this huge cliffs cause huge variances and will always tessellate
		// fully independent of camdist (-> huge/distfromcam ~= huge)
		const float myVariance = std::min(currentVariance[node], varianceMaxLimit);

		const int sizeX = std::max(left.x - right.x, right.x - left.x);
		const int sizeY = std::max(left.y - right.y, right.y - left.y);
		const int size  = std::max(sizeX, sizeY);

		// take distance, variance and patch size into consideration
		TriVariance = (myVariance * PATCH_SIZE * size) * camDistLODFactor;
	}

	// stop tesselation
	if (TriVariance <= 1.0f)
		return;

	Split(tri);

	if (tri->IsBranch()) {
		// triangle was split, also try to split its children
		const int2 center = {(left.x + right.x) >> 1, (left.y + right.y) >> 1};

		RecursTessellate(tri->LeftChild,  apex,  left, center, (node << 1)    );
		RecursTessellate(tri->RightChild, right, apex, center, (node << 1) + 1);
	}
}
예제 #3
0
파일: Patch.cpp 프로젝트: FriedRice/spring
// ---------------------------------------------------------------------
// Tessellate a Patch.
// Will continue to split until the variance metric is met.
//
void Patch::RecursTessellate(TriTreeNode* const& tri, const int2& left, const int2& right, const int2& apex, const int& node)
{
	const bool canFurtherTes = ((abs(left.x - right.x) > 1) || (abs(left.y - right.y) > 1));
	if (!canFurtherTes)
		return;

	float TriVariance;
	const bool varianceSaved = (node < (1 << VARIANCE_DEPTH));
	if (varianceSaved) {
		// make max tessellation viewRadius dependent
		// w/o this huge cliffs cause huge variances and so will always tessellate fully independent of camdist (-> huge/distfromcam ~= huge)
		const float myVariance = std::min(m_CurrentVariance[node], varianceMaxLimit);

		const int sizeX = std::max(left.x - right.x, right.x - left.x);
		const int sizeY = std::max(left.y - right.y, right.y - left.y);
		const int size  = std::max(sizeX, sizeY);

		// Take both distance and variance and patch size into consideration
		TriVariance = (myVariance * PATCH_SIZE * size) * camDistLODFactor;
	} else {
		TriVariance = 10.0f; // >1 -> When variance isn't saved issue further tessellation
	}

	if (TriVariance > 1.0f)
	{
		Split(tri); // Split this triangle.

		if (tri->IsBranch()) { // If this triangle was split, try to split it's children as well.
			const int2 center(
				(left.x + right.x) >> 1, // Compute X coordinate of center of Hypotenuse
				(left.y + right.y) >> 1  // Compute Y coord...
			);
			RecursTessellate(tri->LeftChild,  apex,  left, center, (node << 1)    );
			RecursTessellate(tri->RightChild, right, apex, center, (node << 1) + 1);
		}
	} else {