Exemple #1
0
// ***************************************************************************
void	CVegetable::generateGroupEx(float nbInst, const CVector &posInWorld, const CVector &surfaceNormal, uint vegetSeed, std::vector<CVector2f> &instances) const
{
	nlassert(_Manager);

	// Density modulation.
	//===================

	// compute cos of angle between surfaceNormal and K(0,0,1).
	float	cosAngle= surfaceNormal.z;
	// compute angleFactor density. Use a quadratic, because f'(_CosAngleMiddle)==0.
	float	angleFact= 1 - sqr((cosAngle - _CosAngleMiddle) * _OOCosAngleDist);
	angleFact= max(0.f, angleFact);
	// modulate density with angleFactor.
	nbInst*= angleFact;

	// modulate result by Global Manager density
	nbInst*= _Manager->getGlobalDensity();

	// Now, 0<=nbInst<+oo. If we have 0.1, it means that we have 10% chance to spawn an instance.
	// So add a "random" value (with help of a noise with High frequency)
	// if nbInst==0, we should never have any instance (which may arise if evalOneLevelRandom()==1).
	// hence the 0.99f* which ensure that we do nbInst+= [0..1[.
	nbInst+= 0.99f * RandomGenerator.evalOneLevelRandom(posInWorld);

	// and then get only the integral part.
	sint	nbInstances= NLMISC::OptFastFloor(nbInst);
	nbInstances= max(0, nbInstances);

	// resize the instances
	instances.resize(nbInstances);

	// Position generation.
	//===================
	// For now, generate them randomly.
	static CVector2f	dSeed(0.513f, 0.267f);	// random values.
	CVector				seed= posInWorld;
	seed.z+= vegetSeed * 0.723f;	// 0.723f is a random value.
	for(sint i=0; i<nbInstances; i++)
	{
		instances[i].x= RandomGenerator.evalOneLevelRandom(seed);
		seed.x+= dSeed.x;
		instances[i].y= RandomGenerator.evalOneLevelRandom(seed);
		seed.y+= dSeed.y;
	}
}
Exemple #2
0
// ***************************************************************************
void	CVegetable::generateGroupBiLinear(const CVector &posInWorld, const CVector posInWorldBorder[4], const CVector &surfaceNormal, float area, uint vegetSeed, std::vector<CVector2f> &instances) const
{
	sint	i;
	const	float evenDistribFact= 12.25f;		// an arbitrary value to have a higher frequency for random.

	// compute how many instances to generate on borders of the patch
	// ==================
	float	edgeDensity[4];
	for(i=0; i<4; i++)
	{
		// Get number of instances generated on edges
		edgeDensity[i]= area * Density.eval(posInWorldBorder[i]);
		if(MaxDensity >= 0)
			edgeDensity[i]= min(edgeDensity[i], area * MaxDensity);
		edgeDensity[i]= max(0.f, edgeDensity[i]);
	}
	// Average on center of the patch for each direction.
	float	edgeDensityCenterX;
	float	edgeDensityCenterY;
	edgeDensityCenterX= 0.5f * (edgeDensity[0] + edgeDensity[1]);
	edgeDensityCenterY= 0.5f * (edgeDensity[2] + edgeDensity[3]);


	// Average for all the patch
	float	nbInstAverage= 0.5f * (edgeDensityCenterX + edgeDensityCenterY);


	// generate instances on the patch
	// ==================
	generateGroupEx(nbInstAverage, posInWorld, surfaceNormal, vegetSeed, instances);



	// move instances x/y to follow edge repartition
	// ==================
	// If on a direction, both edges are 0 density, then must do a special formula
	bool	middleX= edgeDensityCenterX<=1;
	bool	middleY= edgeDensityCenterY<=1;
	float	OOEdgeDCX=0.0;
	float	OOEdgeDCY=0.0;
	if(!middleX)	OOEdgeDCX= 1.0f / edgeDensityCenterX;
	if(!middleY)	OOEdgeDCY= 1.0f / edgeDensityCenterY;
	// for all instances
	for(i=0; i<(sint)instances.size(); i++)
	{
		float		x= instances[i].x;
		float		y= instances[i].y;
		// a seed for random.
		CVector		randSeed(x*evenDistribFact, y*evenDistribFact, 0);

		// X change.
		if(middleX)
		{
			// instances are grouped at middle. this is the bijection of easeInEaseOut
			x= x+x - easeInEaseOut(x);
			x= x+x - easeInEaseOut(x);
			instances[i].x= x;
		}
		else
		{
			// Swap X, randomly. swap more on border
			// evaluate the density in X direction we have at this point.
			float	densX= edgeDensity[0]*(1-x) + edgeDensity[1]* x ;
			// If on the side of the lowest density
			if(densX < edgeDensityCenterX)
			{
				// may swap the position
				float	rdSwap= (densX * OOEdgeDCX );
				// (densX * OOEdgeDCX) E [0..1[. The more it is near 0, the more is has chance to be swapped.
				rdSwap+= RandomGenerator.evalOneLevelRandom( randSeed );
				if(rdSwap<1)
					instances[i].x= 1 - instances[i].x;
			}
		}

		// Y change.
		if(middleY)
		{
			// instances are grouped at middle. this is the bijection of easeInEaseOut
			y= y+y - easeInEaseOut(y);
			y= y+y - easeInEaseOut(y);
			instances[i].y= y;
		}
		else
		{
			// Swap Y, randomly. swap more on border
			// evaluate the density in Y direction we have at this point.
			float	densY= edgeDensity[2]*(1-y) + edgeDensity[3]* y ;
			// If on the side of the lowest density
			if(densY < edgeDensityCenterY)
			{
				// may swap the position
				float	rdSwap= (densY * OOEdgeDCY);
				// (densY * OOEdgeDCY) E [0..1[. The more it is near 0, the more is has chance to be swapped.
				rdSwap+= RandomGenerator.evalOneLevelRandom( randSeed );
				if(rdSwap<1)
					instances[i].y= 1 - instances[i].y;
			}
		}

	}

}