// ---This function generates the standard 3D Poisson Disk Sampling Pattern---
///////////////////////////////////////////////////////////////////////////////
short int VDSamplingUpper::genPoissonSampling(VariableDensity *vd)
{
	float fillvalue = vd->getFillvalue();

	// indicate if a suitable mask was found and show the reason
	min_dist_status = 0;

	// parameters to compute a new point
	Point newPoint;
	long newGridPos[2];
	float newRealPos[2];
	long *newGridPosPtr;
	Point actualPoint;
	long *actGridPosPtr;
	float *actRealPosPtr;

	float radius;
	float angle;

	bool tooClose = true;

	int nextIndex = 0; // next index of active_list

	bool found = false;

	// reininitialise the grids, lists and the sampling mask
	anchor = 0;
	nElements = 0;
	for(long i=0; i<height; i++)
	{
		for(long j=0; j<width; j++)
		{
			if ((vd->getFraction()[i][j] != -1) && (vd->getFraction()[i][j] != -3))
			{
				grid[i][j] = noPoint;
				samplingMask[i][j] = 0;
				grid2[i][j] = 0;
			}
			if (vd->getFraction()[i][j] == -3) // border point
			{
				Point actualPoint = grid[i][j];
				filledCircle(actualPoint, vd);
				savePointInActList(actualPoint);
			}
		}
	}
	nSamplingMaskPoints = nSamplingMaskPointsHelper;

	// first point
	///////////////

	if (nElements == 0)
	{
		bool found_first_point = false;

		// create fix first sampling point to the center (not really center if height or width even!)
		if(flag_first)
		{
			// find first point
			newGridPos[0] = long(ceil(float(height)/2)-1);
			newGridPos[1] = long(ceil(float(width)/2)-1);

			// set first point, if partial fourier allows it
			if((newGridPos[0] >= pF_border[0]) && (newGridPos[1] >= pF_border[1]))
			{
				newPoint.setGridPos(newGridPos);
				newRealPos[0] = float(newGridPos[0])+0.5;
				newRealPos[1] = float(newGridPos[1])+0.5;
				newPoint.setRealPos(newRealPos);

				// save the first point
				savePoint(newPoint, vd);

				found_first_point = true;
			}
		}

		// create random first sampling point
		while(found_first_point == false)
		{
			// find the first point
			newRealPos[0] = float(height) * SomeFunctions::randZeroOne(); // was wenn randZeroOne = 1?
			newRealPos[1] = float(width) * SomeFunctions::randZeroOne();
			newPoint.setRealPos(newRealPos);
			newPoint.pointFloatToLong();
			newGridPosPtr = newPoint.getGridPos();

			// set first point, if partial fourier allows it
			if ((newGridPosPtr[0] >= pF_border[0]) && (newGridPosPtr[1] >= pF_border[1]) && vd->getFraction()[newGridPosPtr[0]][newGridPosPtr[1]] != -2)
			{
				// save the first point
				savePoint(newPoint, vd);

				found_first_point = true;
			}
		}
	}

	//cout << "nElements = " << nElements << endl;
	cout << ".";

	// remaining points
	////////////////////

	while( float(nSamplingMaskPoints)/float(nPointsToCreate) < (2.0 - deviation) )
	{

		found = false;

		if(nElements == 0)
		{
			min_dist_status = 2; // min_dist too large
			break;
		}
		else
		{
			// take a random element of the active list
			nextIndex = long(floor(0.5 + SomeFunctions::randZeroOne() * float(nElements-1)));
			actualPoint = LinkedList::showElement(nextIndex, anchor, nElements);
		}

		// randomly generate a new point around the active one allowed region
		// lies between minimal distance (for this voxel) and twice minimal distance
		for(int i = 0; i<nPointsToTest; i++)
		{
			actGridPosPtr = actualPoint.getGridPos();
			actRealPosPtr = actualPoint.getRealPos();

			// random radius depending on fraction
			if (vd->getFraction()[actGridPosPtr[0]][actGridPosPtr[1]] == -3)
			{
				radius = fillvalue * min_dist * (1 + SomeFunctions::randZeroOne());
			}
			else
				radius = vd->getFraction()[actGridPosPtr[0]][actGridPosPtr[1]] * min_dist * ( 1 + SomeFunctions::randZeroOne() );
			if (radius < 1) // avoids setting no point near a point with low values of fraction
				radius = 1;

			// random angle between 0..2pi
			angle = 2 * float(PI) * SomeFunctions::randZeroOne();

			// set position of the new point
			newRealPos[0] = actRealPosPtr[0] + radius * sin(angle);
			newRealPos[1] = actRealPosPtr[1] + radius * cos(angle);
			newPoint.setRealPos(newRealPos);

			// check if the point is in the grid and not inside the partial fourier region
			if ((newRealPos[0] >= pF_border[0]) && (newRealPos[1] >= pF_border[1]) && (newRealPos[0] < height) && (newRealPos[1] < width) && vd->getFraction()[long(newRealPos[0])][long(newRealPos[1])] != -2)
			{
				newPoint.pointFloatToLong();
				newGridPosPtr = newPoint.getGridPos();

				// check if there is already a point or a point disk
				if ( (grid[newGridPosPtr[0]][newGridPosPtr[1]].getIsPoint() == true) || (grid2[newGridPosPtr[0]][newGridPosPtr[1]] == 1))
					continue;

				// check if the newPoint is too close to other points
				checkNeighbourhood( newPoint, tooClose, vd );

				if ( !tooClose )
				{
					found = true;
					savePoint(newPoint,vd);
				}
			}
		}

		// remove actualPoint from active_list
		if ( /*!found &&*/ (nElements != 0) )
		{
				LinkedList::deleteElement(nextIndex, anchor, nElements);
		}
	}



	// Postproc step
	//////////////////

	// check if the number of generated points is in the deviation-range
	//if( (nElements == 0) && !(min_dist_status == 3) && ( float(nSamplingMaskPoints)/float(nPointsToCreate) >= deviation ) && ( float(nSamplingMaskPoints)/float(nPointsToCreate) <= (2-deviation) ) )
	//{
	//	min_dist_status = 3;
	//	cout << "...best approx found!!" << endl << endl;
	//}

	return min_dist_status;
}
void VDSamplingUpper::savePointToGrids(Point p, VariableDensity *vd)
{
	long *gridPos = p.getGridPos();
	grid[gridPos[0]][gridPos[1]] = p;
	filledCircle(p, vd); // fill grid2 with point and circle around it
}
Exemple #3
0
void generate_terrarium() {
	game.map.resize(128,128);
	torch.buf.resize(128,128);

	s16 cx = torch.buf.getw()/2, cy = torch.buf.geth()/2;

	torch.buf.reset();
	torch.buf.cache.reset();
	game.map.reset();

	// glass on the rim
	filledCircle(cx, cy, 60, set_tile_i, (void*)GROUND);
	hollowCircle(cx, cy, 60, set_tile_i, (void*)GLASS);

	AddStars();

	u32 timerVal;

	printf("Growing trees... ");
	startTimer();
	CATrees();
	timerVal = stopTimer();
	printf("done (%.2fs).\n", timerVal*1024/33.513982e6);

	printf("Filling lakes... ");
	startTimer();
	CALakes();
	timerVal = stopTimer();
	printf("done (%.2fs).\n", timerVal*1024/33.513982e6);

	printf("Buying shrubberies... ");
	startTimer();
	AddGrass();
	timerVal = stopTimer();
	printf("done (%.2fs).\n", timerVal*1024/33.513982e6);

	printf("Checking connectivity... ");
	if (checkConnected()) {
		printf("connected.\n");
	} else {
		printf("\1\x1f\x01unconnected\2.\n");
	}

	printf("Simulating inhabitation... ");
	Inhabit();
	printf("done.\n");

	printf("Spawning creatures... ");
	SpawnCreatures();
	printf("done.\n");

	printf("Dropping items... ");
	for (int i = 0; i < 60; i++) {
		s16 x = rand32() % torch.buf.getw(), y = rand32() % torch.buf.geth();
		if (!game.map.solid(x,y)) {
			Object *on = new Object(ROCK);
			stack_item_push(game.map.at(x,y)->objects, on);
		} else i--;
	}
	printf("done.\n");

	s16 x = cx, y = cy;
	while (!game.map.walkable(x, y))
		randwalk(x, y);
	game.player.x = x;
	game.player.y = y;

	game.player.setPos(x,y);
	game.map.at(x,y)->creature = &game.player;

	Object *on = new Object(BATON);
	stack_item_push(game.map.at(x,y)->objects, on);
	on = new Object(LEATHER_JACKET);
	stack_item_push(game.map.at(x,y)->objects, on);
	on = new Object(PAIR_OF_BLUNDSTONE_BOOTS);
	stack_item_push(game.map.at(x,y)->objects, on);

	x = cx; y = cy;

	set_tile(cx+40, cy, FIRE);
	lightsource *li = new lightsource;
	li->set(9<<12, (int)(0.1*(1<<12)), (int)(1.0*(1<<12)), (int)(0.1*(1<<12)));
	li->orig_intensity = li->intensity = 1<<11;
	li->x = (cx+40)<<12; li->y = cy<<12;
	li->flicker = FLICKER_RADIUS;
	game.map.lights.push(li);
	set_tile(cx+30, cy, FIRE);
	li = new lightsource;
	li->set(9<<12, (int)(1.0*(1<<12)), (int)(0.1*(1<<12)), (int)(0.1*(1<<12)));
	li->orig_intensity = li->intensity = 1<<11;
	li->x = (cx+30)<<12; li->y = cy<<12;
	li->flicker = FLICKER_RADIUS;
	game.map.lights.push(li);
	set_tile(cx+35, cy-7, FIRE);
	li = new lightsource;
	li->set(9<<12, (int)(0.1*(1<<12)), (int)(0.1*(1<<12)), (int)(1.0*(1<<12)));
	li->orig_intensity = li->intensity = 1<<11;
	li->x = (cx+35)<<12; li->y = (cy-7)<<12;
	li->flicker = FLICKER_RADIUS;
	game.map.lights.push(li);

	game.map.block.refresh_blocked_from();
	torch.dirty_screen();
	torch.reset_luminance();
}