Beispiel #1
0
void xEditTerrainHeight::_UpdateGeometry()
{
	Terrain * terrain = Environment::Instance()->GetTerrain();

	if (!terrain)
		return ;

	int op = xApp::Instance()->GetOperator();

	Vec3 center = mBrush.position;
	float size = mBrush.size;
	float density = mBrush.density;

	// calculate brush box
	float sx = center.x - size * 0.5f;
	float sz = center.z + size * 0.5f;
	float ex = center.x + size * 0.5f;
	float ez = center.z - size * 0.5f;

	const Terrain::Config & config = terrain->GetConfig();

	int xVertexCount = config.xVertexCount - 1;
	int zVertexCount = config.zVertexCount - 1;

	int isx = (int)Math::Ceil(sx / config.xSize * xVertexCount);
	int iex = (int)(ex / config.xSize * xVertexCount);
	int isz = (int)Math::Ceil((1 - sz / config.zSize) * zVertexCount);
	int iez = (int)((1 - ez / config.zSize) * zVertexCount);

	isx = Math::Maximum(0, isx);
	isz = Math::Maximum(0, isz);
	iex = Math::Maximum(0, iex);
	iez = Math::Maximum(0, iez);

	isx = Math::Minimum(isx, xVertexCount);
	isz = Math::Minimum(isz, zVertexCount);
	iex = Math::Minimum(iex, xVertexCount);
	iez = Math::Minimum(iez, zVertexCount);

	int index = 0;
	Rect rc = { isx, isz, iex, iez };
	float * heights = terrain->LockHeight(rc);

	int w = mBrush.image->GetWidth() - 1;
	int h = mBrush.image->GetHeight() - 1;

	for (int j = isz; j <= iez; ++j)
	{
		for (int i = isx; i <= iex; ++i)
		{
			float x = float(i) / xVertexCount * config.xSize;
			float z = (1 - float(j) / zVertexCount) * config.zSize;

			if (x < 0 || x > config.xSize ||
				z < 0 || z > config.zSize)
				continue ;

			float u = (x - sx) / (ex - sx);
			float v = (z - sz) / (ez - sz);

			u = Math::Maximum(u, 0.0f);
			v = Math::Maximum(v, 0.0f);
			u = Math::Minimum(u, 1.0f);
			v = Math::Minimum(v, 1.0f);

			int iu = int(u * w);
			int iv = int(v * h);
			int iu1 = iu + 1;
			int iv1 = iv + 1;

			iu1 = Math::Minimum(iu1, w);
			iv1 = Math::Minimum(iv1, h);

			float du = u * w - iu;
			float dv = v * h - iv;

			Color4 c0 = mBrush.image->GetColor(iu,  iv);
			Color4 c1 = mBrush.image->GetColor(iu1, iv);
			Color4 c2 = mBrush.image->GetColor(iu,  iv1);
			Color4 c3 = mBrush.image->GetColor(iu1, iv1);

			Color4 cx0 = c0 + (c1 - c0) * du;
			Color4 cx1 = c2 + (c3 - c2) * du;

			Color4 cy = cx0 + (cx1 - cx0) * dv;

			float d = cy.r * density;

			if (mOp == eUp)
				heights[index++] += d;
			else if (mOp == eDown)
				heights[index++] -= d;
			else if (mOp == eSmooth)
			{
				float ha = terrain->_getHeight(i - 1, j + 0);
				float hb = terrain->_getHeight(i + 0, j - 1);
				float hc = terrain->_getHeight(i + 1, j + 0);
				float hd = terrain->_getHeight(i + 0, j + 1);
				float hm = heights[index];
				float hAvg = (hm + ha + hb + hc + hd) / 5;
				
				heights[index++] = Math::Lerp(hm, hAvg, d);
			}
		}
	}

	terrain->UnlockHeight();
}