Exemplo n.º 1
0
int main( int argc, char **argv ) {

	uint32 cycle, nbCycles = 5;
	if (argc == 1)
		cycle = 112952;
	else
	{
		if (argc >= 2)
			sscanf(argv[1], "%d", &cycle);
		if (argc >= 3)
			sscanf(argv[2], "%d", &nbCycles);
	}
	// nbCycles*9/(60*24*365) years worth
	// 1 year = 58400 weather cycles
	printf("; %dbit platform\n", cpuPlatform);
	printf("; cycle=%d, nbCycles=%d\n", cycle, nbCycles);

	NLMISC::CNoiseValue nv;

	NLMISC::OptFastFloorBegin();
	for(uint32 i=cycle; i < (cycle + nbCycles); ++i){
		float noiseValue = nv.eval(NLMISC::CVector(i * 0.99524f, i * 0.85422f, i * -0.45722f));
		noiseValue = fmodf(noiseValue * 10.f, 1.f);
		printf("%d, %f\n", i, noiseValue);
	}
	NLMISC::OptFastFloorEnd();


	return 0;
}
Exemplo n.º 2
0
// *******************************************************************************************
float computeUniformNoise(const NLMISC::CNoiseValue &nv, const CVector &pos)
{
	NLMISC::OptFastFloorBegin();
	float value = nv.eval(pos);
	value = 10.f * fmodf(value, 0.1f); // make repartition more uniform
	NLMISC::OptFastFloorEnd();
	return value;
}
Exemplo n.º 3
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;
	}
}
Exemplo n.º 4
0
namespace NL3D
{


// ***************************************************************************
// Generate random value, but seed is spacial. Take a high frequency, so it gets more the aspect of random.
static	NLMISC::CNoiseValue		RandomGenerator(0,1, 7.68f);


// ***************************************************************************
CVegetable::CVegetable()
{
	// Ground style density.
	setAngleGround(0);

	// Density not maximised.
	MaxDensity= -1;

	// No scale.
	Sxy.Abs= Sz.Abs= 1;
	Sxy.Rand= Sz.Rand= 0;
	// No rotation.
	Rx.Abs= Ry.Abs= Rz.Abs= 0;
	Rx.Rand= Ry.Rand= Rz.Rand= 0;
	// No BendFactor.
	BendFactor.Abs= 1;
	BendFactor.Rand= 0;
	BendFrequencyFactor= 1;

	// Appear at 0.
	DistType= 0;

	_Manager= NULL;
}


// ***************************************************************************
void	CVegetable::setAngleGround(float cosAngleMin)
{
	_AngleType= AngleGround;

	_CosAngleMin= cosAngleMin;
	// We must be at densityFactor==1, when cosAngle==1, keeping the same formula.
	_CosAngleMax= 1 + (1-cosAngleMin);

	// precalc
	_CosAngleMiddle= (_CosAngleMin + _CosAngleMax)/2;
	_OOCosAngleDist= _CosAngleMax - _CosAngleMiddle;
	if(_OOCosAngleDist)
		_OOCosAngleDist= 1.0f / _OOCosAngleDist;
}

// ***************************************************************************
void	CVegetable::setAngleCeiling(float cosAngleMax)
{
	_AngleType= AngleCeiling;

	_CosAngleMax= cosAngleMax;
	// We must be at densityFactor==1, when cosAngle==-1, keeping the same formula.
	_CosAngleMin= -1 - (cosAngleMax-(-1));

	// precalc
	_CosAngleMiddle= (_CosAngleMin + _CosAngleMax)/2;
	_OOCosAngleDist= _CosAngleMax - _CosAngleMiddle;
	if(_OOCosAngleDist)
		_OOCosAngleDist= 1.0f / _OOCosAngleDist;
}

// ***************************************************************************
void	CVegetable::setAngleWall(float cosAngleMin, float cosAngleMax)
{
	_AngleType= AngleWall;

	_CosAngleMin= cosAngleMin;
	_CosAngleMax= cosAngleMax;

	// precalc
	_CosAngleMiddle= (_CosAngleMin + _CosAngleMax)/2;
	_OOCosAngleDist= _CosAngleMax - _CosAngleMiddle;
	if(_OOCosAngleDist)
		_OOCosAngleDist= 1.0f / _OOCosAngleDist;
}


// ***************************************************************************
void	CVegetable::registerToManager(CVegetableManager *manager)
{
	nlassert(manager);
	_Manager= manager;
	_VegetableShape= _Manager->getVegetableShape(ShapeName);
}


// ***************************************************************************
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;
	}
}


// ***************************************************************************
void	CVegetable::generateGroup(const CVector &posInWorld, const CVector &surfaceNormal, float area, uint vegetSeed, std::vector<CVector2f> &instances) const
{
	// number of instances to generate
	float	dens= Density.eval(posInWorld);
	if(MaxDensity >= 0)
		dens= min(dens, MaxDensity);
	float	nbInst= area * dens;

	// modulate by normal and generate them.
	generateGroupEx(nbInst, posInWorld, surfaceNormal, vegetSeed, instances);
}


// ***************************************************************************
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;
			}
		}

	}

}


// ***************************************************************************
void	CVegetable::reserveIgAddInstances(CVegetableInstanceGroupReserve &vegetIgReserve, TVegetableWater vegetWaterState, uint numInstances) const
{
	nlassert(_Manager);

	if (_VegetableShape)
		_Manager->reserveIgAddInstances(vegetIgReserve, _VegetableShape, (CVegetableManager::TVegetableWater)vegetWaterState, numInstances);
}


// ***************************************************************************
void	CVegetable::generateInstance(CVegetableInstanceGroup *ig, const NLMISC::CMatrix &posInWorld,
		const NLMISC::CRGBAF &modulateAmbientColor, const NLMISC::CRGBAF &modulateDiffuseColor, float blendDistMax,
		TVegetableWater vegetWaterState, CVegetableUV8 dlmUV) const
{
	nlassert(_Manager);


	CVector		seed= posInWorld.getPos();

	// Generate Matrix.
	// ===============

	// Generate a random Scale / Rotation matrix.
	CMatrix		randomMat;
	// setup rotation
	CVector		rot;
	rot.x= Rx.eval(seed);
	rot.y= Ry.eval(seed);
	rot.z= Rz.eval(seed);
	randomMat.setRot(rot, CMatrix::ZXY);
	// scale.
	if(Sxy.Abs!=0 || Sxy.Rand!=0 || Sz.Abs!=0 || Sz.Rand!=0)
	{
		CVector		scale;
		scale.x= scale.y= Sxy.eval(seed);
		scale.z= Sz.eval(seed);
		randomMat.scale(scale);
	}

	// Final Matrix.
	CMatrix		finalMatrix;
	finalMatrix= posInWorld * randomMat;

	// Generate Color and factor
	// ===============
	CRGBAF		materialColor(1,1,1,1);
	// evaluate gradients. If none, color not modified.
	Color.eval(seed, materialColor);
	// modulate with user
	CRGBAF		ambient, diffuse;
	if(_VegetableShape && _VegetableShape->Lighted)
	{
		ambient= modulateAmbientColor * materialColor;
		diffuse= modulateDiffuseColor * materialColor;
	}
	else
	{
		ambient= materialColor;
		diffuse= materialColor;
	}

	// Generate a bendFactor
	float	bendFactor= BendFactor.eval(seed);
	// Generate a bendPhase
	float	bendPhase= BendPhase.eval(seed);


	// Append to the vegetableManager
	// ===============
	if (_VegetableShape)
	{
		_Manager->addInstance(ig, _VegetableShape, finalMatrix, ambient, diffuse,
			bendFactor, bendPhase, BendFrequencyFactor, blendDistMax,
			(CVegetableManager::TVegetableWater)vegetWaterState, dlmUV);
	}
}


// ***************************************************************************
void	CVegetable::serial(NLMISC::IStream &f)
{
	/*
	Version 1:
		- add BendFrequencyFactor
	Version 0:
		- base version
	*/
	sint	ver= f.serialVersion(1);

	f.serial(ShapeName);
	f.serial(Density);
	f.serial(MaxDensity);
	f.serial(_CosAngleMin, _CosAngleMax, _CosAngleMiddle, _OOCosAngleDist);
	f.serialEnum(_AngleType);
	f.serial(Sxy, Sz);
	f.serial(Rx, Ry, Rz);
	f.serial(BendFactor);
	f.serial(BendPhase);
	f.serial(Color);
	f.serial(DistType);

	if(ver>=1)
		f.serial(BendFrequencyFactor);
	else
		BendFrequencyFactor= 1;
}


} // NL3D
Exemplo n.º 5
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;
			}
		}

	}

}