⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 radprim.cpp

📁 赫赫大名的 OGRE 游戏引擎
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	if (newUPatches == uPatches() && newVPatches == vPatches()) return false;

	RadPatchArray	newPatches;
	fstl::intArray	newPatchesCount;
	RadPatch	defaultPatch;
	defaultPatch.area()   = 0;
	defaultPatch.energy() = geom::Color3(0,0,0);
	defaultPatch.origin() = geom::Point3(0,0,0);
	defaultPatch.plane()  = plane();
	newPatches.populate(defaultPatch, newUPatches * newVPatches);
	newPatchesCount.populate(0, newUPatches * newVPatches);

	for(unsigned int v = 0; v < vPatches(); ++v)
	{
		for(unsigned int u = 0; u < uPatches(); ++u)
		{
			unsigned int	idx = v * uPatches() + u;
			unsigned int	newIdx = v/2 * newUPatches + u/2;

			// Skip unused patches

			if (!patches()[idx].area()) continue;

			newPatches[newIdx].area() += patches()[idx].area();
			newPatches[newIdx].energy() += patches()[idx].energy();
			newPatches[newIdx].origin() += patches()[idx].origin();
			newPatchesCount[newIdx]++;
		}
	}

	// Get the origin as the average of the other centers

	for (unsigned int j = 0; j < newPatches.size(); ++j)
	{
		if (newPatchesCount[j]) newPatches[j].origin() /= static_cast<float>(newPatchesCount[j]);
	}

	patches() = newPatches;
	uPatches() = newUPatches;
	vPatches() = newVPatches;

	return true;
}

// ---------------------------------------------------------------------------------------------------------------------------------
// Hacked from the one in fsgl::Primitive...
// ---------------------------------------------------------------------------------------------------------------------------------

bool	RadPrim::localBisect(const geom::Plane3 & clipPlane, RadPrim & back)
{
	// First, classify all points. This allows us to avoid any bisection if possible

	fstl::floatArray	classifications;
	classifications.reserve(xyz().size());
	{
		bool	pos = false;
		bool	neg = false;

		for (unsigned int i = 0; i < xyz().size(); ++i)
		{
			// Get the distance from the plane to the vertex

			float	dist = clipPlane.distance(xyz()[i]);

			// Classify the point

			if (dist > -EPSILON && dist < EPSILON)	dist = 0.0f;
			else if (dist > 0)			pos = true;
			else					neg = true;

			// Keep track

			classifications += dist;
		}

		// Special (and necessary) case:
		//
		// If the polygon rests on the plane, it could be associated with either side (or neither side)... so we pick one.
		// The only criteria we have for this choice is to use the normals....
		//
		// The specific case ("dot product > 0 == associate with front") was chosen for cases in the octree -- a polygon facing
		// the interior of a node, but resting on an outer-most-node boundary. We want it associated with the node, not thrown
		// out completely.

		if (!pos && !neg)
		{
			// Associate with front

			if ((plane().vector() ^ clipPlane.vector()) > 0)
			{
				pos = true;
			}

			// Associate with back

			else
			{
				neg = true;
			}
		}

		// If no negative points, return an empty negative polygon

		if (!neg)
		{
			back.xyz().erase();
			back.uv().erase();
			back.texuv().erase();

			return true;
		}

		// If no positive points, return self as negative polygon

		else if (!pos)
		{
			back.xyz() = xyz();
			back.uv() = uv();
			back.texuv() = texuv();
			back.plane() = plane();

			xyz().erase();
			uv().erase();
			texuv().erase();
			return true;
		}

	}

	// Our result is stored here

	back.xyz() = xyz();
	back.uv() = uv();
	back.texuv() = texuv();
	back.plane() = plane();

	geom::Point3Array &	negXYZ = back.xyz();
	geom::Point2Array &	negUV  = back.uv();
	geom::Point2Array &	negTUV = back.texuv();
	negXYZ.erase();
	negXYZ.reserve(xyz().size());
	negUV.erase();
	negUV.reserve(xyz().size());
	negTUV.erase();
	negTUV.reserve(xyz().size());

	geom::Point3Array	posXYZ;
	geom::Point2Array	posUV;
	geom::Point2Array	posTUV;
	posXYZ.reserve(xyz().size());
	posUV.reserve(xyz().size());
	posTUV.reserve(xyz().size());

	// Visit all points in the list, adding points that are on the front-side of the current plane. If an edge bisects the plane,
	// add the bisection point.

	unsigned int	v0 = xyz().size() - 1;

	for (unsigned int v1 = 0; v1 < xyz().size(); ++v1)
	{
		const geom::Point3 &	p0 = xyz()[v0];
		const geom::Point3 &	p1 = xyz()[v1];
		const geom::Point2 &	l0 = uv()[v0];
		const geom::Point2 &	l1 = uv()[v1];
		const geom::Point2 &	t0 = texuv()[v0];
		const geom::Point2 &	t1 = texuv()[v1];
		float			d0 = classifications[v0];
		float			d1 = classifications[v1];

		// neg->neg non-crossover?

		if (d0 < 0 && d1 < 0)
		{
			negXYZ += p1;
			negUV += l1;
			negTUV += t1;
		}

		// neg->zed crossover?

		else if (d0 < 0 && d1 == 0)
		{
			negXYZ += p1;
			posXYZ += p1;

			negUV += l1;
			posUV += l1;

			negTUV += t1;
			posTUV += t1;
		}

		// neg->pos crossover?

		else if (d0 < 0 && d1 > 0)
		{
			float	delta = d0 / (d1-d0);

			geom::Point3	bisectionXYZ = p0 - (p1 - p0) * delta;
			negXYZ += bisectionXYZ;
			posXYZ += bisectionXYZ;
			posXYZ += p1;

			geom::Point2	bisectionUV = l0 - (l1 - l0) * delta;
			negUV += bisectionUV;
			posUV += bisectionUV;
			posUV += l1;

			geom::Point2	bisectionTUV = t0 - (t1 - t0) * delta;
			negTUV += bisectionTUV;
			posTUV += bisectionTUV;
			posTUV += t1;
		}

		// zed->pos crossover?

		else if (d0 == 0 && d1 > 0)
		{
			posXYZ += p1;
			posUV += l1;
			posTUV += t1;
		}


		// zed->neg crossover?

		else if (d0 == 0 && d1 < 0)
		{
			negXYZ += p1;
			negUV += l1;
			negTUV += t1;
		}


		// pos->pos non-crossover?

		else if (d0 > 0 && d1 > 0)
		{
			posXYZ += p1;
			posUV += l1;
			posTUV += t1;
		}

		// pos->neg crossover?

		else if (d0 > 0 && d1 < 0)
		{
			float	delta = d1 / (d0-d1);

			geom::Point3	bisectionXYZ = p1 - (p0 - p1) * delta;
			posXYZ += bisectionXYZ;
			negXYZ += bisectionXYZ;
			negXYZ += p1;

			geom::Point2	bisectionUV = l1 - (l0 - l1) * delta;
			posUV  += bisectionUV;
			negUV  += bisectionUV;
			negUV  += l1;

			geom::Point2	bisectionTUV = t1 - (t0 - t1) * delta;
			posTUV  += bisectionTUV;
			negTUV  += bisectionTUV;
			negTUV  += t1;
		}

		// pos->zed crossover?

		else if (d0 > 0 && d1 == 0)
		{
			posXYZ += p1;
			negXYZ += p1;

			posUV += l1;
			negUV += l1;

			posTUV += t1;
			negTUV += t1;
		}

		// If the edge rests completely on the plane, then we've got a concave polygon. How's that, you say? Well...
		// This really shouldn't ever happen since an edge that rests on the plane means it can never cross the plane
		// without going concave, but inaccuracy issues do happen...
		//
		// Chances are (and we're guessing here!) that p0 and p1 are nearly (or completely) identical, in which case
		// we'll just ignore this, and it'll skip the extra vertex.

		else if (d0 == 0 && d1 == 0)
		{
			// Do nothing!
		}

		// Next vertex, please!

		v0 = v1;
	}

	// Replace the vertices with just those found on the postiive side

	xyz() = posXYZ;
	uv() = posUV;
	texuv() = posTUV;

	// Done

	return true;
}

// ---------------------------------------------------------------------------------------------------------------------------------

bool	RadPrim::bisectNoTextures(const geom::Plane3 & clipPlane, RadPrim & back)
{
	// First, classify all points. This allows us to avoid any bisection if possible

	fstl::floatArray	classifications;
	classifications.reserve(xyz().size());
	{
		bool	pos = false;
		bool	neg = false;

		for (unsigned int i = 0; i < xyz().size(); ++i)
		{
			// Get the distance from the plane to the vertex

			float	dist = clipPlane.distance(xyz()[i]);

			// Classify the point

			if (dist > -EPSILON && dist < EPSILON)	dist = 0.0f;
			else if (dist > 0)			pos = true;
			else					neg = true;

			// Keep track

			classifications += dist;
		}

		// Special (and necessary) case:
		//
		// If the polygon rests on the plane, it could be associated with either side (or neither side)... so we pick one.
		// The only criteria we have for this choice is to use the normals....
		//
		// The specific case ("dot product > 0 == associate with front") was chosen for cases in the octree -- a polygon facing
		// the interior of a node, but resting on an outer-most-node boundary. We want it associated with the node, not thrown
		// out completely.

		if (!pos && !neg)
		{
			// Associate with front

			if ((plane().vector() ^ clipPlane.vector()) > 0)
			{
				pos = true;
			}

			// Associate with back

			else
			{
				neg = true;
			}
		}

		// If no negative points, return an empty negative polygon

		if (!neg)
		{
			back.xyz().erase();
			return true;
		}

		// If no positive points, return self as negative polygon

		else if (!pos)
		{
			back.xyz() = xyz();
			back.plane() = plane();

			xyz().erase();
			return true;
		}

	}

	// Our result is stored here

	back.xyz() = xyz();
	back.plane() = plane();

	geom::Point3Array &	negXYZ = back.xyz();
	negXYZ.erase();
	negXYZ.reserve(xyz().size());

	geom::Point3Array	posXYZ;
	posXYZ.reserve(xyz().size());

	// Visit all points in the list, adding points that are on the front-side of the current plane. If an edge bisects the plane,
	// add the bisection point.

	unsigned int	v0 = xyz().size() - 1;

	for (unsigned int v1 = 0; v1 < xyz().size(); ++v1)
	{
		const geom::Point3 &	p0 = xyz()[v0];
		const geom::Point3 &	p1 = xyz()[v1];
		float			d0 = classifications[v0];
		float			d1 = classifications[v1];

		// neg->neg non-crossover?

		if (d0 < 0 && d1 < 0)
		{
			negXYZ += p1;
		}

		// neg->zed crossover?

		else if (d0 < 0 && d1 == 0)
		{
			negXYZ += p1;
			posXYZ += p1;
		}

		// neg->pos crossover?

		else if (d0 < 0 && d1 > 0)
		{
			float	delta = d0 / (d1-d0);

			geom::Point3	bisectionXYZ = p0 - (p1 - p0) * delta;
			negXYZ += bisectionXYZ;
			posXYZ += bisectionXYZ;
			posXYZ += p1;
		}

		// zed->pos crossover?

		else if (d0 == 0 && d1 > 0)
		{
			posXYZ += p1;
		}


		// zed->neg crossover?

		else if (d0 == 0 && d1 < 0)
		{
			negXYZ += p1;
		}


		// pos->pos non-crossover?

		else if (d0 > 0 && d1 > 0)
		{
			posXYZ += p1;
		}

		// pos->neg crossover?

		else if (d0 > 0 && d1 < 0)
		{
			float	delta = d1 / (d0-d1);

			geom::Point3	bisectionXYZ = p1 - (p0 - p1) * delta;
			posXYZ += bisectionXYZ;
			negXYZ += bisectionXYZ;
			negXYZ += p1;
		}

		// pos->zed crossover?

		else if (d0 > 0 && d1 == 0)
		{
			posXYZ += p1;
			negXYZ += p1;
		}

		// If the edge rests completely on the plane, then we've got a concave polygon. How's that, you say? Well...
		// This really shouldn't ever happen since an edge that rests on the plane means it can never cross the plane
		// without going concave, but inaccuracy issues do happen...
		//
		// Chances are (and we're guessing here!) that p0 and p1 are nearly (or completely) identical, in which case
		// we'll just ignore this, and it'll skip the extra vertex.

		else if (d0 == 0 && d1 == 0)
		{
			// Do nothing!
		}

		// Next vertex, please!

		v0 = v1;
	}

	// Replace the vertices with just those found on the postiive side

	xyz() = posXYZ;

	// Done

	return true;
}

// ---------------------------------------------------------------------------------------------------------------------------------
// RadPrim.cpp - End of file
// ---------------------------------------------------------------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -