Exemple #1
0
void WorldRenderer::GenerateGrass(const Vector2UINT& sectorCoords)
{
	// Grass Turned Off
	if ( !zGrassDensity ) 
	{
		return;
	}

	// Delete previous grass if existing.
	auto grassIterator = this->zGrass.find(sectorCoords);

	// Create Sector Rect
	Rect sectorRect;
	sectorRect.topLeft.x = (float)sectorCoords.x * FSECTOR_WORLD_SIZE;
	sectorRect.topLeft.y = (float)sectorCoords.y * FSECTOR_WORLD_SIZE;
	sectorRect.size.x = FSECTOR_WORLD_SIZE;
	sectorRect.size.y = FSECTOR_WORLD_SIZE;

	// Check if inside clip range
	Circle clipCircle(zGraphics->GetCamera()->GetPosition().GetXZ(), zGrassFarDistance);

	// Check Intersection
	if ( !DoesIntersect(sectorRect, clipCircle) )
	{
		if ( grassIterator != this->zGrass.end() )
		{
			// Remove from graphics engine.
			this->zGraphics->DeleteBillboardCollection(grassIterator->second);

			// Remove from map.
			this->zGrass.erase(grassIterator);
		}
		
		return;
	}

	// Delete Old Grass
	if( grassIterator != this->zGrass.end() )
	{
		// Remove from graphics engine.
		this->zGraphics->DeleteBillboardCollection(grassIterator->second);

		// Reset
		grassIterator->second = 0;
	}

	// First check if the sector has any grass texture
	Sector* sector = this->zWorld->GetSector(sectorCoords);
	bool found = false;
	for(unsigned int i = 0; i < SECTOR_BLEND_CHANNELS && !found; ++i)
	{
		if(strcmp(sector->GetTextureName(i), "01_v02-Moss.png") == 0)
		{
			found = true;
		}
		else if(strcmp(sector->GetTextureName(i), "06_v01-MossDark.png") == 0)
		{
			found = true;
		}
		else if(strcmp(sector->GetTextureName(i), "07_v01-MossLight.png") == 0)
		{
			found = true;
		}
	}

	// No Grass Textures Found
	if(!found)
	{
		return;
	}

	float width = FSECTOR_WORLD_SIZE;
	float depth = FSECTOR_WORLD_SIZE; 
	unsigned int sqrtGrassDensity = (unsigned int)sqrt((long)this->zGrassDensity);
	float xDiff = width / sqrtGrassDensity;
	float zDiff = depth / sqrtGrassDensity;
	Vector2 grassPos = Vector2(0.0f);
	Vector2 terrainPosXZ = sectorRect.topLeft;
	float blendValueGrassLight = 0.0f;
	float blendValueGrassMedium = 0.0f;
	float blendValueGrassDark = 0.0f;
	float blendThreshHold = 0.32f;
	const static float RGB_MIN_MAX = 50.0f / 255.0f;
	Vector3* positions = new Vector3[this->zGrassDensity];
	Vector2* sizes = new Vector2[this->zGrassDensity];
	Vector3* colors = new Vector3[this->zGrassDensity];
	fast_rand_seed = sectorCoords.x + sectorCoords.y;
	float rndMaxInv = 1.0f / (float)RAND_MAX;
	float grassWidth = 0.0f;
	float grassHeight = 0.0f;
	float terrainY = 0.0f;
	Vector2 offsetVector = Vector2(xDiff, zDiff) * 0.5f;
	
	unsigned int index = 0;
	float totBlendValue = 0.0f;
	
	//Values taken from average texture color.
	Vector3 colorGrassLight = Vector3(91.0f, 131.0f, 65.0f) / 255.0f;
	Vector3 colorGrassMedium = Vector3(107.0f, 142.0f, 77.0f) / 255.0f;
	Vector3 colorGrassDark = Vector3(68.0f, 104.0f, 45.0f)  / 255.0f;
	Vector3 rndGrassColorOffsetVecGrassLight = Vector3(0.0f, 0.0f, 0.0f);
	Vector3 rndGrassColorOffsetVecGrassMedium = Vector3(0.0f, 0.0f, 0.0f);
	Vector3 rndGrassColorOffsetVecGrassDark = Vector3(0.0f, 0.0f, 0.0f);

	float minMaxDistX = xDiff * 0.5f - zGrassNeightbourDistance * 0.5f;
	float minMaxDistZ = zDiff * 0.5f - zGrassNeightbourDistance * 0.5f;

	for(unsigned int x = 0; x < sqrtGrassDensity; ++x)
	{
		for(unsigned int z = 0; z < sqrtGrassDensity; ++z)
		{
			// Initial position
			grassPos = terrainPosXZ + Vector2((float)x * xDiff, (float)z * zDiff) + offsetVector;

			// Move initial position randomly
			grassPos.x += fastrand() * rndMaxInv * 2.0f * minMaxDistX - minMaxDistX;
			grassPos.y += fastrand() * rndMaxInv * 2.0f * minMaxDistZ - minMaxDistZ;

			// Randomize Size
			grassWidth = fastrand() * rndMaxInv * (zGrassWidthMax-zGrassWidthMin) + zGrassWidthMin;
			grassHeight = fastrand() * rndMaxInv * (zGrassHeightMax-zGrassHeightMin) + zGrassHeightMin;

			// Randomize dark grass RGB = rgb[-RGB_MIN_MAX, 0]
			rndGrassColorOffsetVecGrassDark.y = fastrand() * rndMaxInv * RGB_MIN_MAX - RGB_MIN_MAX;

			// Randomize medium grass RGB = rgb[-RGB_MIN_MAX / 2, RGB_MIN_MAX / 2]
			rndGrassColorOffsetVecGrassMedium.y = (fastrand() * rndMaxInv * 2.0f * RGB_MIN_MAX - RGB_MIN_MAX)*0.5f;

			// Randomize light grass RGB = rgb[0, RGB_MIN_MAX]
			rndGrassColorOffsetVecGrassLight.y = fastrand() * rndMaxInv * RGB_MIN_MAX;

			try
			{
				terrainY = zWorld->CalcHeightAtWorldPos(grassPos);
			}
			catch (...)
			{
				continue;
			}

			//blendValueGrassLight + blendValueGrassMedium + blendValueGrassDark -> range[0,1]
			blendValueGrassLight = this->zWorld->GetAmountOfTexture(grassPos, "07_v01-MossLight.png");
			blendValueGrassMedium = this->zWorld->GetAmountOfTexture(grassPos, "01_v02-Moss.png");
			blendValueGrassDark = this->zWorld->GetAmountOfTexture(grassPos, "06_v01-MossDark.png");

			totBlendValue = blendValueGrassLight + blendValueGrassMedium + blendValueGrassDark;
			if(totBlendValue > blendThreshHold) 
			{
				//totBlendValue range[blendThreshHold, 1], we want [0,1]
				float tmp = totBlendValue - blendThreshHold; //range[0, 1 - blendThreshHold];
				tmp /= 1.0f - blendThreshHold;
				totBlendValue = tmp;
				//Set size
				grassHeight *= totBlendValue; //modify grass height depending on blend values
				//If it is below minGrassHeight, don't add it. (It can never be greater than maxHeight)
				if(grassHeight >= zGrassHeightMin)
				{
					sizes[index] = Vector2(grassWidth, grassHeight);
					//Set position
					positions[index] = Vector3(grassPos.x, terrainY + grassHeight * 0.5f, grassPos.y);
					//Set color
					Vector3 test = 	(colorGrassLight + rndGrassColorOffsetVecGrassLight) * blendValueGrassLight
								+	(colorGrassMedium + rndGrassColorOffsetVecGrassMedium) * blendValueGrassMedium
								+	(colorGrassDark + rndGrassColorOffsetVecGrassDark) * blendValueGrassDark
								+	Vector3(1.0f, 1.0f, 1.0f) //Color is a multiplier.
								-	Vector3(0.8f, 0.8f, 0.8f); //Adjust ambient & diffuse TTILLMAN
					colors[index] =	test;
					//Increase index(number of grass objects)
					index++;
				}
			}
		}
	}

	
	//Add grass
	//No offset vector needed since grass positions is in world space.
	if(index > 0)
	{
		this->zGrass[sectorCoords] = this->zGraphics->CreateBillboardCollection(index, positions, sizes, colors, Vector3(0.0f, 0.0f, 0.0f), "Media/Grass.png"); 
		this->zGrass[sectorCoords]->SetRenderShadowFlag(false); //Don't render shadows.
		this->zGrass[sectorCoords]->SetCullFarDistance(zGrassFarDistance);
		this->zGrass[sectorCoords]->SetCullNearDistance(zGrassNearDistance);
	}
	
	//Delete data 
	delete [] positions;
	delete [] sizes;
	delete [] colors;
}