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

📄 radgen.cpp

📁 使用stl技术,(还没看,是听说的)
💻 CPP
📖 第 1 页 / 共 4 页
字号:
	geom::Color3	ae = totalAbsorbedEnergy();
	geom::Color3	ee = totalEscapedEnergy();

	float	initial = ie.r() + ie.g() + ie.b();
	float	absorbed = ae.r() + ae.g() + ae.b();
	float	escaped = ee.r() + ee.g() + ee.b();
	float	remaining = initial - absorbed - escaped;

	float	percentThisPass = energyThisPass() / remaining * 100;
	float	percentEnergy = absorbed / (initial - escaped) * 100;
	prog.setCurrentPercent(percentEnergy);

	prog.setLabel1("Iterations:");
	if (maxIterations())
	{
		prog.setText1(fstl::string(iterationsProcessed()) + " of " + fstl::string(maxIterationsCount()));
	}
	else
	{
		prog.setText1(fstl::string(iterationsProcessed()));
	}

	prog.setLabel2("Initial (abs/esc) Energy:");
	char	disp[/*SK:MAX_PATH*/256];
	if (lightsToProcess())
	{
		sprintf(disp, "[processing lights]");
	}
	else
	{
		sprintf(disp, "%u (%.2f%% / %.2f%%)", static_cast<unsigned int>(initial * displayMultiplier), absorbed/initial*100, escaped/initial*100);
	}
	prog.setText2(disp);

	prog.setLabel3("Energy remaining:");
	prog.setText3(fstl::string(static_cast<unsigned int>(remaining * displayMultiplier)));

	prog.setLabel4("Convergence target:");

	if (checkConvergence && !directLightOnly())
	{
		sprintf(disp, "%u (%.5f%%)", convergence(), static_cast<float>(convergence()) / (energyThisPass() * displayMultiplier) * 100);
		prog.setText4(disp);
	}
	else
	{
		if (directLightOnly())	prog.setText4("N/A (direct light only)");
		else			prog.setText4("N/A");
	}

	prog.setLabel5("Energy shot this pass:");
	sprintf(disp, "%.2f", energyThisPass() * displayMultiplier);
	prog.setText5(disp);

	prog.setLabel6("Form factor calculation method:");
	if (lightsToProcess())
	{
		prog.setText6("Point light estimation");
	}
	else
	{
		if (useNusselt())	prog.setText6("Nusselt's Analogy");
		else			prog.setText6("Standard estimation");
	}

	prog.setLabel7("Input file:");
	fstl::string	ifn = inputFilename();
	int	idx = ifn.rfind("\\");
	if (idx != -1) ifn = ifn.substring(idx+1);
	prog.setText7(ifn);

	if (adaptivePatchSubdivision())
	{
		prog.setLabel8("Adaptive subdivision threshold:");
		sprintf(disp, "%u (%.3f%% there)", adaptiveThreshold(), adaptiveThreshold() / (energyThisPass() * displayMultiplier) * 100);
		prog.setText8(disp);
	}
	else
	{
		prog.setLabel8("");
		prog.setText8("");
	}

	prog.setLabel9("Total patches:");
	prog.setText9(fstl::string(totalPatches()) + " (cur: " + fstl::string(subdivisionU()) + "x" + fstl::string(subdivisionV()) + ", max: " + fstl::string(adaptiveMaxSubdivisionU()) + "x" + fstl::string(adaptiveMaxSubdivisionV()) + ")");

	prog.setLabel10("Total elements:");
	prog.setText10(fstl::string(totalElements()));

	// If they've reached convergence, tell them to stop
	//
	// Note that we don't check for convergence when told, and when there are lights to process, because we want at least
	// all light sources processed, as a minimum.

	if (!lightsToProcess() && checkConvergence && (energyThisPass() * displayMultiplier) <= convergence()) return false;

	// Or tell them to stop when the user requests it...

	return !prog.stopRequested();
}

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

void	RadGen::distributeInitialEnergy()
{
	progress()->setCurrentStatus("Slicing up geometry into patches/elements");

	unsigned int	idx = 0;
	for (RadPrimList::node *i = geometry().polys().head(); i; i = i->next(), ++idx)
	{
		if (!(idx&0xf))
		{
			progress()->setCurrentPercent(static_cast<float>(idx) / static_cast<float>(geometry().polys().size()) * 100.0f);
			if (progress()->stopRequested()) throw "";
		}

		RadPrim &	prim = i->data();
		prim.originalPrimitive() = &prim;
		prim.prepare(subdivisionU(), subdivisionV());

		if (prim.illuminationColor() != geom::Color3(0,0,0))
		{
			int	minU, maxU, minV, maxV;
			prim.calcIntegerUVExtents(minU, maxU, minV, maxV);

			RadLMap	&	lm = geometry().lightmaps()[prim.textureID()];

			float	totalArea = (prim.uXFormVector() % prim.vXFormVector()).length();
			float *	areas = &prim.elementAreas()[0];
			for (unsigned int v = minV; v <= static_cast<unsigned int>(maxV); ++v)
			{
				for (unsigned int u = minU; u <= static_cast<unsigned int>(maxU); ++u, ++areas)
				{
					if (*areas)
					{
						float	partialArea = *areas / totalArea;
						lm.data()[v*lm.width()+u] = prim.illuminationColor() * static_cast<float>(areaLightMultiplier()) * partialArea;
					}
				}
			}
		}
	}
}

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

void	RadGen::countPatchesAndElements()
{
	progress()->setCurrentStatus("Counting patches and elements");

	totalPatches() = 0;
	totalElements() = 0;

	unsigned int	idx = 0;
	for (RadPrimList::node *i = geometry().polys().head(); i; i = i->next(), ++idx)
	{
		if (!(idx&0xf))
		{
			progress()->setCurrentPercent(static_cast<float>(idx) / static_cast<float>(geometry().polys().size()) * 100.0f);
			if (progress()->stopRequested()) throw "";
		}

		RadPrim &	prim = i->data();

		// Count patches

		for (unsigned int j = 0; j < prim.patches().size(); ++j)
		{
			if (prim.patches()[j].area()) totalPatches()++;
		}

		for (unsigned int k = 0; k < prim.elementAreas().size(); ++k)
		{
			if (prim.elementAreas()[k]) totalElements()++;
		}
	}
}

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

geom::Color3	RadGen::calcAmbientTerm()
{
	progress()->setCurrentStatus("Calculating the ambient term");

	// We'll need the total area and total average reflectivity

	float		totalArea = 0;
	geom::Color3	pAve(0,0,0);
	{
		for (RadPrimList::node *i = geometry().polys().head(); i; i = i->next())
		{
			RadPrim &	p = i->data();
			float	area = p.calcArea();
			totalArea += area;
			pAve += p.reflectanceColor() * area;
		}
	}

	// Calculate the ambient term

	pAve /= totalArea;
	geom::Color3	totalUnshotEnergy = (initialEnergy() - totalAbsorbedEnergy() - totalEscapedEnergy());
	geom::Color3	estimatedAmbientTerm = pAve * totalUnshotEnergy / totalArea;

	unsigned int	idx = 0;
	for (RadPrimList::node *i = geometry().polys().head(); i; i = i->next(), ++idx)
	{
		if (!(idx&0xf))
		{
			progress()->setCurrentPercent(static_cast<float>(idx) / static_cast<float>(geometry().polys().size()) * 100.0f);
			if (progress()->stopRequested()) throw "";
		}

		RadPrim &	p = i->data();
		RadLMap &	lm = geometry().lightmaps()[p.textureID()];

		int	minU, maxU, minV, maxV;
		p.calcIntegerUVExtents(minU, maxU, minV, maxV);

		float	totalArea = (p.uXFormVector() % p.vXFormVector()).length();

		// Remove softened edges around polygons
		{
			int	fIndex = 0;
			for (unsigned int v = minV; v <= static_cast<unsigned int>(maxV); ++v)
			{
				for (unsigned int u = minU; u <= static_cast<unsigned int>(maxU); ++u, ++fIndex)
				{
					// Area

					float	eArea = p.elementAreas()[fIndex];

					// Skip unused texels

					if (eArea <= 0) continue;

					// Add the ambient term

					lm.data()[v*lm.width()+u] += estimatedAmbientTerm * p.reflectanceColor() * eArea * static_cast<float>(areaLightMultiplier());
				}
			}
		}
	}

	return estimatedAmbientTerm;
}

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

void	RadGen::expandEdges()
{
	progress()->setCurrentStatus("Correcting edges in the lightmaps");

	// Duplicate the lightmaps for mask purposes
// PDNDEBUG -- maskMaps is a bad name.. and using lightmaps is wasteful... could be just an array of float arrays...
	RadLMapArray		maskMaps = geometry().lightmaps();

	// Clear out the maskmaps
	{
		geom::Color3	blank(0,0,0);

		for (unsigned int i = 0; i < maskMaps.size(); ++i)
		{
			RadLMap &	mm = maskMaps[i];
			unsigned int	size = mm.width() * mm.height();
			geom::Color3 *	mPtr = &mm.data()[0];
			for (unsigned int i = 0; i < size; ++i, ++mPtr)
			{
				*mPtr = blank;
			}
		}
	}

// PDNDEBUG - hack
float	totalArea = 0;

	// Fill the mask with element areas (i.e. this is essentially the antialiasing information)
	{
		unsigned int	idx = 0;
		for (RadPrimList::node *i = geometry().polys().head(); i; i = i->next(), ++idx)
		{
			if (!(idx&0xf))
			{
				progress()->setCurrentPercent(static_cast<float>(idx) / static_cast<float>(geometry().polys().size()) * 50.0f);
				if (progress()->stopRequested()) throw "";
			}

			RadPrim &	p = i->data();
			RadLMap &	mm = maskMaps[p.textureID()];

// PDNDEBUG - hack -- can we replace all calculations of "total area" with a global value, now that we're creating our own lightmaps?
totalArea = (p.uXFormVector() % p.vXFormVector()).length();

			int	minU, maxU, minV, maxV;
			p.calcIntegerUVExtents(minU, maxU, minV, maxV);

			// We'll go through and place the element areas where polygons occupy the lightmaps
			{
				unsigned int	fIndex = 0;
				for (unsigned int v = minV; v <= static_cast<unsigned int>(maxV); ++v)
				{
					unsigned int	vIndex = v * mm.width();
					for (unsigned int u = minU; u <= static_cast<unsigned int>(maxU); ++u, ++fIndex)
					{
						// If this texel is not occupied, skip it

						if (!p.elementAreas()[fIndex]) continue;

						// ADD the texel area into the red component of the lightmap for this texel
						//
						// This allows us to know the total usage of a texel from a series of possibly
						// connected polygons

						mm.data()[vIndex + u].r() += p.elementAreas()[fIndex];
					}
				}
			}
		}
	}

	// Un-antialias the lightmaps
	{
		for (unsigned int i = 0; i < maskMaps.size(); ++i)
		{
			RadLMap &	mm = maskMaps[i];
			RadLMap &	lm = geometry().lightmaps()[i];
			geom::Color3 *	mPtr = &mm.data()[0];
			geom::Color3 *	cPtr = &lm.data()[0];

			unsigned int	size = mm.width() * mm.height();
			for (unsigned int i = 0; i < size; ++i, ++mPtr, ++cPtr)
			{
				// Skip unoccupied or wholly occupied pixels

				if (mPtr->r() == 0 || mPtr->r() >= totalArea) continue;

				// Adjust lightmap texel -- this is effectively un-antialiasing the texel

				*cPtr *= totalArea / mPtr->r();
			}
		}
	}

	// Do the filtering...
	{
		for (unsigned int i = 0; i < geometry().lightmaps().size(); ++i)
		{
			if (!(i&0xf))
			{
				progress()->setCurrentPercent(static_cast<float>(i) / static_cast<float>(geometry().polys().size()) * 50.0f + 50.0f);
				if (progress()->stopRequested()) throw "";
			}

			// Lightmap & mask

			RadLMap &	lm = geometry().lightmaps()[i];
			RadLMap &	mm = maskMaps[i];
			unsigned int	lw = lm.width();
			unsigned int	lh = lm.height();

			// Here we do our pixel extension... it works like this:
			//
			// Each pixel that does _not_ contain any mask area, will be the averge of its neighbors that _do_ have
			// a mask area (if any).
			{
				for (unsigned int v = 0; v < lh; ++v)
				{
					// Current row for the [M]ask and [C]olor maps (for convenience)...

					geom::Color3 *	cmRow = &mm.data()[v*lw];
					geom::Color3 *	ccRow = &lm.data()[v*lw];

					// Top row for the [M]ask and [C]olor maps (for convenience)...

					geom::Color3 *	tmRow = static_cast<geom::Color3 *>(0);
					geom::Color3 *	tcRow = static_cast<geom::Color3 *>(0);
					if (v > 0)
					{
						tmRow = cmRow - lw;
						tcRow = ccRow - lw;
					}

⌨️ 快捷键说明

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