Ejemplo n.º 1
0
void EnemyGrunt::render(sf::RenderTarget &rt) {
	sf::Sprite shadowSprite;
	shadowSprite.setTexture(_assets->_gruntShadow);

	shadowSprite.setOrigin(_assets->_gruntShadow.getSize().x * 0.5f, _assets->_gruntShadow.getSize().y * 0.5f);

	shadowSprite.setPosition(_position);

	rt.draw(shadowSprite);

	sf::Sprite footSprite;
	footSprite.setTexture(_assets->_gruntFoot);

	footSprite.setOrigin(2.0f, 2.5f);

	sf::Vector2f perpendicular(std::cos(_rotation * ltbl::_pi / 180.0f), std::sin(_rotation * ltbl::_pi / 180.0f));
	sf::Vector2f forward(perpendicular.y, -perpendicular.x);

	const float feetSpread = 1.5f;
	const float feetStepDistance = 2.5f;

	float leftFootOffset = std::sin(2.0f * ltbl::_pi * _footCycle);

	footSprite.setRotation(_rotation);

	footSprite.setPosition(_position - perpendicular * feetSpread + forward * feetStepDistance * leftFootOffset - forward * 1.0f);

	rt.draw(footSprite);

	footSprite.setPosition(_position + perpendicular * feetSpread - forward * feetStepDistance * leftFootOffset - forward * 1.0f);

	rt.draw(footSprite);

	sf::Sprite bodySprite;

	if (_pTarget == nullptr) {
		bodySprite.setTexture(_assets->_gruntBodyWalk);

		bodySprite.setPosition(_position);
	}
	else {
		std::uniform_real_distribution<float> noiseDist(-0.5f, 0.5f);

		// Show flash for only a bit of the flash cycle time
		if (_firingCycle < 0.3f) {
			bodySprite.setPosition(_position + sf::Vector2f(noiseDist(getGame()->_generator), noiseDist(getGame()->_generator)));
			bodySprite.setTexture(_assets->_gruntBodyFlashes[_currentFlash]);
		}
		else {
			bodySprite.setPosition(_position);
			bodySprite.setTexture(_assets->_gruntBodyNoFire);
		}
	}

	bodySprite.setOrigin(sf::Vector2f(_assets->_gruntBodyWalk.getSize().x * 0.5f, _assets->_gruntBodyWalk.getSize().y * 0.5f));

	bodySprite.setRotation(_rotation + leftFootOffset * 8.0f); // Sway a bit

	rt.draw(bodySprite);
}
Ejemplo n.º 2
0
Archivo: pool.cpp Proyecto: vidarn/mgrl
void
PoolRoom::decorateRoom(Tile *tiles, TileFactory *tileFactory, std::vector<DecorationPlacement> &places)
{
	//TODO make sure it doesn't go outside the dungeon (or at least handle that case)
    boost::random::uniform_real_distribution<> noiseDist(-3.f,4.f);
	for(int y=-m_radius;y<=m_radius;y++){
		for(int x=-m_radius;x<=m_radius;x++){
			if(sqrtf(float(x*x)+float(y*y)) < float(m_radius)-0.6f+noiseDist(RAND)){
                setTile(x,y,"Water Stream", tiles, tileFactory);
			}
		}
	}
}
Ejemplo n.º 3
0
void
ShardRoom::decorateRoom(Tile *tiles, TileFactory *tileFactory, std::vector<DecorationPlacement> &places)
{
    boost::random::uniform_real_distribution<> noiseDist(-3.f,4.f);
	for(int y=-m_radius;y<=m_radius;y++){
		for(int x=-m_radius;x<=m_radius;x++){
			if(sqrtf(float(x*x)+float(y*y)) < float(m_radius)-0.6f+noiseDist(RAND)){
                setTile(x,y,"Crystal Floor", tiles, tileFactory);
			}
		}
	}
    if(m_orb){
        setTile(0,0,"Orb of Knowledge", tiles, tileFactory);
        setTile( 1, 1,"Shard of Knowledge", tiles, tileFactory);
        setTile( 1,-1,"Shard of Knowledge", tiles, tileFactory);
        setTile(-1, 1,"Shard of Knowledge", tiles, tileFactory);
        setTile(-1,-1,"Shard of Knowledge", tiles, tileFactory);
    }
    else{
        setTile(0,0,"Shard of Knowledge", tiles, tileFactory);
    }
}
Ejemplo n.º 4
0
int main() {
	std::mt19937 generator(time(nullptr));

	sys::ComputeSystem cs;

	cs.create(sys::ComputeSystem::_gpu);

	sys::ComputeProgram prog;

	prog.loadFromFile("resources/neoKernels.cl", cs);

	std::vector<Level> levels;

	std::unordered_set<char> tileDataCharset;
	std::unordered_set<char> objectDataCharset;

	loadLevels("userlevels.txt", levels, tileDataCharset, objectDataCharset);

	// --------------------------- Create the Sparse Coder ---------------------------

	const int numTiles = levels.front()._tileData.length();

	const int charsetSize = 128 + 2; // + 2 indicating the portion it is on (01 for tiles, 10 for objects)

	const cl::size_type visDim = std::ceil(std::sqrt(static_cast<float>(charsetSize)));
	const int visArea = visDim * visDim;

	const int maxObjects = 1000;

	cl::Image2D input = cl::Image2D(cs.getContext(), CL_MEM_READ_WRITE, cl::ImageFormat(CL_R, CL_FLOAT), visDim, visDim);

	std::vector<float> inputData(visArea, 0.0f);
	std::vector<float> predData(visArea, 0.0f);

	std::vector<neo::PredictiveHierarchy::LayerDesc> layerDescs(3);

	layerDescs[0]._size = { 16, 16 };
	layerDescs[1]._size = { 16, 16 };
	layerDescs[2]._size = { 16, 16 };

	neo::PredictiveHierarchy ph;

	ph.createRandom(cs, prog, { static_cast<int>(visDim), static_cast<int>(visDim) }, layerDescs, { -0.01f, 0.01f }, generator);

	ph._whiteningKernelRadius = 1;

	// Learn levels
	std::uniform_int_distribution<int> levelDist(0, levels.size() - 1);

	for (int iter = 0; iter < 20; iter++) {
		// Choose random level
		int index = levelDist(generator);

		const Level &l = levels[index];

		// Set mode for tiles
		inputData[charsetSize - 2] = 0.0f;
		inputData[charsetSize - 1] = 1.0f;

		// Run through once to get PH ready
		inputData['#'] = 1.0f;

		cs.getQueue().enqueueWriteImage(input, CL_TRUE, cl::array<cl::size_type, 3> { 0, 0, 0 }, cl::array<cl::size_type, 3> { visDim, visDim, 1 }, 0, 0, inputData.data());

		ph.simStep(cs, input);

		inputData['#'] = 0.0f;

		// Run through tile data
		for (int i = 0; i < l._tileData.length(); i++) {
			// Set character to 1
			inputData[l._tileData[i]] = 1.0f;

			cs.getQueue().enqueueWriteImage(input, CL_TRUE, cl::array<cl::size_type, 3> { 0, 0, 0 }, cl::array<cl::size_type, 3> { visDim, visDim, 1 }, 0, 0, inputData.data());

			ph.simStep(cs, input);

			// Unset character
			inputData[l._tileData[i]] = 0.0f;
		}

		// Set mode for objects
		inputData[charsetSize - 2] = 1.0f;
		inputData[charsetSize - 1] = 0.0f;

		// Run through once to get PH ready
		inputData['#'] = 1.0f;

		cs.getQueue().enqueueWriteImage(input, CL_TRUE, { 0, 0, 0 }, { visDim, visDim, 1 }, 0, 0, inputData.data());

		ph.simStep(cs, input);

		inputData['#'] = 0.0f;

		// Run through object data
		for (int i = 0; i < l._objectData.length(); i++) {
			// Set character to 1
			inputData[l._objectData[i]] = 1.0f;

			cs.getQueue().enqueueWriteImage(input, CL_TRUE, { 0, 0, 0 }, { visDim, visDim, 1 }, 0, 0, inputData.data());

			ph.simStep(cs, input);

			// Unset character
			inputData[l._objectData[i]] = 0.0f;
		}

		std::cout << "Went over level #" << (index + 1) << " \"" << l._name << "\"" << std::endl;
	}

	// Generate new maps
	std::ofstream toFile("generatedNLevels.txt");

	std::normal_distribution<float> noiseDist(0.0f, 1.0f);

	for (int i = 0; i < 10; i++) {
		toFile << "$" << "Generated Level " << (i + 1) << "#NeoRL#Experimental#";

		// Generated level data


		// Set mode for tiles
		inputData[charsetSize - 2] = 0.0f;
		inputData[charsetSize - 1] = 1.0f;

		// Run through once to get PH ready
		//cs.getQueue().enqueueWriteImage(input, CL_TRUE, cl::array<cl::size_type, 3> { 0, 0, 0 }, cl::array<cl::size_type, 3> { visDim, visDim, 1 }, 0, 0, inputData.data());

		//ph.simStep(cs, input);

		char prevChar = 0;

		for (int i = 0; i < numTiles; i++) {
			// Set character to 1
			inputData[prevChar] = 1.0f;

			cs.getQueue().enqueueWriteImage(input, CL_TRUE, cl::array<cl::size_type, 3> { 0, 0, 0 }, cl::array<cl::size_type, 3> { visDim, visDim, 1 }, 0, 0, inputData.data());

			ph.simStep(cs, input, false);

			// Unset character
			inputData[prevChar] = 0.0f;

			char newChar = 0;

			cs.getQueue().enqueueReadImage(ph.getPrediction(), CL_TRUE, cl::array<cl::size_type, 3> { 0, 0, 0 }, cl::array<cl::size_type, 3> { visDim, visDim, 1 }, 0, 0, predData.data());
	
			for (int j = 1; j < charsetSize - 2; j++)
				if (predData[j] > predData[newChar])
					newChar = j;

			// Add new character
			toFile << newChar;

			prevChar = newChar;
		}

		toFile << "|";

		// Set mode for objects
		inputData[charsetSize - 2] = 1.0f;
		inputData[charsetSize - 1] = 0.0f;

		// Run through once to get PH ready
		//cs.getQueue().enqueueWriteImage(input, CL_TRUE, cl::array<cl::size_type, 3> { 0, 0, 0 }, cl::array<cl::size_type, 3> { visDim, visDim, 1 }, 0, 0, inputData.data());

		//ph.simStep(cs, input);

		prevChar = 0;

		for (int i = 0; i < maxObjects; i++) {
			// Set character to 1
			inputData[prevChar] = 1.0f;

			std::vector<float> noisyInputData = inputData;

			for (int j = 0; j < noisyInputData.size(); j++) {
				noisyInputData[j] += noiseDist(generator) * 0.1f;
			}

			cs.getQueue().enqueueWriteImage(input, CL_TRUE, cl::array<cl::size_type, 3> { 0, 0, 0 }, cl::array<cl::size_type, 3> { visDim, visDim, 1 }, 0, 0, inputData.data());

			ph.simStep(cs, input, false);

			// Unset character
			inputData[prevChar] = 0.0f;

			char newChar = 0;

			cs.getQueue().enqueueReadImage(ph.getPrediction(), CL_TRUE, cl::array<cl::size_type, 3> { 0, 0, 0 }, cl::array<cl::size_type, 3> { visDim, visDim, 1 }, 0, 0, predData.data());

			for (int j = 1; j < charsetSize - 2; j++)
				if (predData[j] > predData[newChar])
					newChar = j;

			// If is delimiter, break
			if (newChar == '#')
				break;

			// Add new character
			toFile << newChar;

			prevChar = newChar;
		}

		toFile << "#" << std::endl << std::endl;
	}

	return 0;
}
Ejemplo n.º 5
0
int main() {
	sf::RenderWindow window;

	sf::ContextSettings glContextSettings;
	glContextSettings.antialiasingLevel = 4;

	window.create(sf::VideoMode(800, 600), "BIDInet", sf::Style::Default, glContextSettings);

	window.setFramerateLimit(60);
	window.setVerticalSyncEnabled(true);

	std::mt19937 generator(time(nullptr));

	/*sys::ComputeSystem cs;

	cs.create(sys::ComputeSystem::_gpu);

	sys::ComputeProgram program;

	program.loadFromFile("resources/bidinet.cl", cs);

	bidi::BIDInet bidinet;

	std::vector<bidi::BIDInet::InputType> inputTypes(64, bidi::BIDInet::_state);

	const int numStates = 3 + 3 + 2 + 2 + 1 + 2 + 2;
	const int numActions = 3 + 3 + 2 + 2;
	const int numQ = 8;

	for (int i = 0; i < numStates; i++)
		inputTypes[i] = bidi::BIDInet::_state;

	for (int i = 0; i < numActions; i++)
		inputTypes[numStates + i] = bidi::BIDInet::_action;

	std::vector<bidi::BIDInet::LayerDesc> layerDescs(2);

	layerDescs[0]._fbRadius = 16;
	layerDescs[1]._width = 8;
	layerDescs[1]._height = 8;

	bidinet.createRandom(cs, program, 8, 8, inputTypes, layerDescs, -0.1f, 0.1f, 0.001f, 1.0f, generator);*/

	// Physics
	std::shared_ptr<b2World> world = std::make_shared<b2World>(b2Vec2(0.0f, -9.81f));

	const float pixelsPerMeter = 256.0f;

	const float groundWidth = 5000.0f;
	const float groundHeight = 5.0f;

	// Create ground
	b2BodyDef groundBodyDef;
	groundBodyDef.position.Set(0.0f, 0.0f);

	b2Body* groundBody = world->CreateBody(&groundBodyDef);

	b2PolygonShape groundBox;
	groundBox.SetAsBox(groundWidth * 0.5f, groundHeight * 0.5f);

	groundBody->CreateFixture(&groundBox, 0.0f);

	sf::Texture skyTexture;

	skyTexture.loadFromFile("resources/background1.png");

	skyTexture.setSmooth(true);

	sf::Texture floorTexture;
	
	floorTexture.loadFromFile("resources/floor1.png");

	floorTexture.setRepeated(true);
	floorTexture.setSmooth(true);

	Runner runner0;

	runner0.createDefault(world, b2Vec2(0.0f, 2.762f), 0.0f, 1);

	//Runner runner1;

	//runner1.createDefault(world, b2Vec2(0.0f, 2.762f), 0.0f, 2);

	//deep::FERL ferl;

	const int clockCount = 4;

	//ferl.createRandom(3 + 3 + 2 + 2 + 1 + 2 + 2 + recCount + clockCount, 3 + 3 + 2 + 2 + recCount, 32, 0.01f, generator);

	//std::vector<float> prevAction(ferl.getNumAction(), 0.0f);

	deep::CSRL prsdr;

	const int inputCount = 3 + 3 + 2 + 2 + 1 + 2 + 2 + clockCount + 1;
	const int outputCount = 3 + 3 + 2 + 2;

	/*std::vector<deep::CSRL::LayerDesc> layerDescs(2);

	layerDescs[0]._width = 4;
	layerDescs[0]._height = 4;

	layerDescs[1]._width = 3;
	layerDescs[1]._height = 3;

	std::vector<deep::CSRL::InputType> inputTypes(7 * 7, deep::CSRL::_state);

	for (int i = 0; i < inputCount; i++)
		inputTypes[i] = deep::CSRL::_state;

	for (int i = 0; i < outputCount; i++)
		inputTypes[i + inputCount] = deep::CSRL::_action;

	prsdr.createRandom(7, 7, 8, inputTypes, layerDescs, -0.01f, 0.01f, 0.01f, 0.05f, 0.5f, generator);
	*/
	neo::Agent agent;

	std::vector<neo::Agent::LayerDesc> layerDescs(2);

	layerDescs[0]._width = 8;
	layerDescs[0]._height = 8;

	layerDescs[1]._width = 4;
	layerDescs[1]._height = 4;

	std::vector<int> actionIndices;

	for (int i = 0; i < outputCount; i++)
		actionIndices.push_back(inputCount + i);

	agent.createRandom(8, 8, 8, layerDescs, -0.01f, 0.01f, 0.01f, 0.05f, 0.1f, generator);

	vis::CSRLVisualizer v;

	v.create(512);

	sf::RenderTexture rt;

	rt.create(512, 512);

	// ---------------------------- Game Loop -----------------------------

	sf::View view = window.getDefaultView();

	bool quit = false;

	sf::Clock clock;

	float dt = 0.017f;

	int steps = 0;

	do {
		clock.restart();

		// ----------------------------- Input -----------------------------

		sf::Event windowEvent;

		while (window.pollEvent(windowEvent))
		{
			switch (windowEvent.type)
			{
			case sf::Event::Closed:
				quit = true;
				break;
			}
		}

		if (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))
			quit = true;

		//bidinet.simStep(cs, 0.0f, 0.98f, 0.001f, 0.95f, 0.01f, 0.01f, generator);

		const float maxRunnerBodyAngle = 0.3f;
		const float runnerBodyAngleStab = 10.0f;

		std::normal_distribution<float> noiseDist(0.0f, 0.05f);

		{
			float reward;
			
			if (sf::Keyboard::isKeyPressed(sf::Keyboard::K))
				reward = -runner0._pBody->GetLinearVelocity().x;
			else
				reward = runner0._pBody->GetLinearVelocity().x;

			std::vector<float> state;

			runner0.getStateVector(state);

			std::vector<float> action(3 + 3 + 2 + 2);

			/*for (int a = 0; a < recCount; a++)
				state.push_back(sdrrl.getAction(10 + a));

			for (int a = 0; a < clockCount; a++)
				state.push_back(std::sin(steps / 60.0f * 2.0f * a * 2.0f * 3.141596f) * 0.5f + 0.5f);

			for (int i = 0; i < state.size(); i++)
				sdrrl.setState(i, state[i]);*/

			/*for (int a = 0; a < recCount; a++)
				state.push_back(prsdr.getPrediction(inputCount + 10 + a));

			for (int a = 0; a < clockCount; a++)
				state.push_back(std::sin(steps / 60.0f * 2.0f * a * 2.0f * 3.141596f) * 0.5f + 0.5f);

			for (int i = 0; i < state.size(); i++)
				sdrrl.setState(i, state[i]);*/

			for (int a = 0; a < clockCount; a++)
				state.push_back(std::sin(steps / 60.0f * 2.0f * a * 2.0f * 3.141596f) * 0.5f + 0.5f);

			for (int i = 0; i < state.size(); i++)
				agent.setInput(i, state[i]);

			for (int i = 0; i < action.size(); i++)
				agent.setInput(inputCount + i, std::min(1.0f, std::max(0.0f, agent.getPrediction(inputCount + i) * 0.5f + 0.5f + noiseDist(generator))));

			//sdrrl.simStep(reward, 0.05f, 0.99f, 32, 5, 0.1f, 0.01f, 0.1f, 0.01f, 0.01f, 0.05f, 32, 0.05f, 0.98f, 0.05f, 0.01f, 0.01f, 4.0f, generator);
			//prsdr.simStep(reward, generator);
			agent.simStep(reward, generator);

			for (int i = 0; i < action.size(); i++)
				action[i] = std::min(1.0f, std::max(0.0f, agent.getPrediction(inputCount + i) * 0.5f + 0.5f));

			runner0.motorUpdate(action, 12.0f);

			// Keep upright
			if (std::abs(runner0._pBody->GetAngle()) > maxRunnerBodyAngle)
				runner0._pBody->SetAngularVelocity(-runnerBodyAngleStab * runner0._pBody->GetAngle());
		}

		/*{
			float reward;

			if (sf::Keyboard::isKeyPressed(sf::Keyboard::K))
				reward = -runner1._pBody->GetLinearVelocity().x;
			else
				reward = runner1._pBody->GetLinearVelocity().x;

			std::vector<float> state;

			runner1.getStateVector(state);

			std::vector<float> action(3 + 3 + 2 + 2 + recCount);

			for (int a = 0; a < recCount; a++)
				state.push_back(prevAction[prevAction.size() - recCount + a]);

			for (int a = 0; a < clockCount; a++)
				state.push_back(std::sin(steps / 60.0f * 2.0f * a * 2.0f * 3.141596f));

			// Bias
			state.push_back(1.0f);

			//ferl.step(state, action, reward, 0.5f, 0.99f, 0.98f, 0.05f, 16, 4, 0.05f, 0.01f, 0.05f, 600, 64, 0.01f, generator);

			for (int i = 0; i < action.size(); i++)
				action[i] = action[i] * 0.5f + 0.5f;

			prevAction = action;

			runner1.motorUpdate(action, 12.0f);

			// Keep upright
			if (std::abs(runner1._pBody->GetAngle()) > maxRunnerBodyAngle)
				runner1._pBody->SetAngularVelocity(-runnerBodyAngleStab * runner1._pBody->GetAngle());
		}*/

		int subSteps = 1;

		for (int ss = 0; ss < subSteps; ss++) {
			world->ClearForces();

			world->Step(1.0f / 60.0f / subSteps, 64, 64);
		}

		if (!sf::Keyboard::isKeyPressed(sf::Keyboard::T) || steps % 200 == 1) {
			// -------------------------------------------------------------------

			//if (!sf::Keyboard::isKeyPressed(sf::Keyboard::B))
			//	view.setCenter(runner1._pBody->GetPosition().x * pixelsPerMeter, -runner1._pBody->GetPosition().y * pixelsPerMeter);
			//else
				view.setCenter(runner0._pBody->GetPosition().x * pixelsPerMeter, -runner0._pBody->GetPosition().y * pixelsPerMeter);

			// Draw sky
			sf::Sprite skySprite;
			skySprite.setTexture(skyTexture);

			window.setView(window.getDefaultView());

			window.draw(skySprite);

			window.setView(view);

			sf::RectangleShape floorShape;
			floorShape.setSize(sf::Vector2f(groundWidth * pixelsPerMeter, groundHeight * pixelsPerMeter));
			floorShape.setTexture(&floorTexture);
			floorShape.setTextureRect(sf::IntRect(0, 0, groundWidth * pixelsPerMeter, groundHeight * pixelsPerMeter));

			floorShape.setOrigin(sf::Vector2f(groundWidth * pixelsPerMeter * 0.5f, groundHeight * pixelsPerMeter * 0.5f));

			window.draw(floorShape);

			//runner1.renderDefault(window, sf::Color::Blue, pixelsPerMeter);
			runner0.renderDefault(window, sf::Color::Red, pixelsPerMeter);

			/*sf::Image img;
			img.create(sdrrl.getNumCells(), 1);

			for (int i = 0; i < sdrrl.getNumCells(); i++) {
				sf::Color c = sf::Color::Black;

				c.r = c.g = c.b = 255.0f * sdrrl.getCellState(i);

				img.setPixel(i, 0, c);
			}

			float scale = 4.0f;

			sf::Texture tex;
			tex.loadFromImage(img);

			sf::Sprite s;
			s.setTexture(tex);

			s.setScale(sf::Vector2f(scale, scale));

			s.setPosition(sf::Vector2f(0.0f, window.getSize().y - scale * img.getSize().y));

			window.setView(window.getDefaultView());

			window.draw(s);*/

			window.setView(window.getDefaultView());

			rt.clear(sf::Color::White);

			v.update(rt, sf::Vector2f(rt.getSize().x * 0.5f, rt.getSize().y * 0.5f), sf::Vector2f(2.0f, 2.0f), prsdr, 532352);

			rt.display();

			sf::Sprite s;

			s.setTexture(rt.getTexture());

			s.setScale(0.5f, 0.5f);

			window.draw(s);
			
			window.setView(view);

			window.display();
		}
		else {
			if (steps % 100 == 0)
				std::cout << "Steps: " << steps << " Distance: " << runner0._pBody->GetPosition().x << std::endl;
		}

		//dt = clock.getElapsedTime().asSeconds();

		steps++;

	} while (!quit);

	world->DestroyBody(groundBody);

	return 0;
}
void plane3d_estimation_using_ransac()
{
	//const double PLANE_EQN[4] = { 0.5774, -0.5774, 0.5774, -1.1547 };  // x - y + z - 2 = 0.
	const double PLANE_EQN[4] = { 1, -1, 1, -2 };  // x - y + z - 2 = 0.
	const size_t NUM_INLIERS = 100;
	const size_t NUM_OUTLIERS = 500;
	const double& eps = swl::MathConstant::EPS;

	// Generate random points.
	std::vector<std::array<double, 3>> sample;
	sample.reserve(NUM_INLIERS + NUM_OUTLIERS);
	{
		std::random_device seedDevice;
		std::mt19937 RNG = std::mt19937(seedDevice());

		std::uniform_real_distribution<double> unifDistInlier(-3, 3);  // [-3, 3].
		const double sigma = 0.1;
		//const double sigma = 0.2;  // Much harder.
		std::normal_distribution<double> noiseDist(0.0, sigma);
		for (size_t i = 0; i < NUM_INLIERS; ++i)
		{
			const double x = unifDistInlier(RNG), y = unifDistInlier(RNG), z = -(PLANE_EQN[0] * x + PLANE_EQN[1] * y + PLANE_EQN[3]) / PLANE_EQN[2];
			sample.push_back({ x + noiseDist(RNG), y + noiseDist(RNG), z + noiseDist(RNG) });
		}

		std::uniform_real_distribution<double> unifDistOutlier(-5, 5);  // [-5, 5].
		for (size_t i = 0; i < NUM_OUTLIERS; ++i)
			sample.push_back({ unifDistOutlier(RNG), unifDistOutlier(RNG), unifDistOutlier(RNG) });

		std::random_shuffle(sample.begin(), sample.end());
	}

	// RANSAC.
	//const size_t minimalSampleSize = 3;
	local::Plane3RansacEstimator ransac(sample);

	const size_t maxIterationCount = 500;
	const size_t minInlierCount = 50;
	const double alarmRatio = 0.5;
	const bool isProsacSampling = true;

	std::cout << "********* RANSAC of Plane3" << std::endl;
	{
		const double distanceThreshold = 0.1;  // Distance threshold.

		const size_t inlierCount = ransac.runRANSAC(maxIterationCount, minInlierCount, alarmRatio, isProsacSampling, distanceThreshold);

		std::cout << "\tThe number of iterations: " << ransac.getIterationCount() << std::endl;
		std::cout << "\tThe number of inliers: " << inlierCount << std::endl;
		if (inlierCount != (size_t)-1 && inlierCount >= minInlierCount)
		{
			if (std::abs(ransac.getA()) > eps)
				std::cout << "\tEstimated plane model: " << "x + " << (ransac.getB() / ransac.getA()) << " * y + " << (ransac.getC() / ransac.getA()) << " * z + " << (ransac.getD() / ransac.getA()) << " = 0" << std::endl;
			else 
				std::cout << "\tEstimated plane model: " << ransac.getA() << " * x + " << ransac.getB() << " * y + " << ransac.getC() << " * z + " << ransac.getD() << " = 0" << std::endl;
			std::cout << "\tTrue plane model:      " << "x + " << (PLANE_EQN[1] / PLANE_EQN[0]) << " * y + " << (PLANE_EQN[2] / PLANE_EQN[0]) << " * z + " << (PLANE_EQN[3] / PLANE_EQN[0]) << " = 0" << std::endl;

			const std::vector<bool> &inlierFlags = ransac.getInlierFlags();
			std::cout << "\tIndices of inliers: ";
			size_t idx = 0;
			for (std::vector<bool>::const_iterator cit = inlierFlags.begin(); cit != inlierFlags.end(); ++cit, ++idx)
				if (*cit) std::cout << idx << ", ";
			std::cout << std::endl;
		}
		else
			std::cout << "\tRANSAC failed" << std::endl;
	}

	std::cout << "********* MLESAC of Plane3" << std::endl;
	{
		const double inlierSquaredStandardDeviation = 0.001;  // Inliers' squared standard deviation. Assume that inliers follow normal distribution.
		const double inlierThresholdProbability = 0.2;  // Inliers' threshold probability. Assume that outliers follow uniform distribution.
		const size_t maxEMIterationCount = 50;

		const size_t inlierCount = ransac.runMLESAC(maxIterationCount, minInlierCount, alarmRatio, isProsacSampling, inlierSquaredStandardDeviation, inlierThresholdProbability, maxEMIterationCount);

		std::cout << "\tThe number of iterations: " << ransac.getIterationCount() << std::endl;
		std::cout << "\tThe number of inliers: " << inlierCount << std::endl;
		if (inlierCount != (size_t)-1 && inlierCount >= minInlierCount)
		{
			if (std::abs(ransac.getA()) > eps)
				std::cout << "\tEstimated plane model: " << "x + " << (ransac.getB() / ransac.getA()) << " * y + " << (ransac.getC() / ransac.getA()) << " * z + " << (ransac.getD() / ransac.getA()) << " = 0" << std::endl;
			else
				std::cout << "\tEstimated plane model: " << ransac.getA() << " * x + " << ransac.getB() << " * y + " << ransac.getC() << " * z + " << ransac.getD() << " = 0" << std::endl;
			std::cout << "\tTrue plane model:      " << "x + " << (PLANE_EQN[1] / PLANE_EQN[0]) << " * y + " << (PLANE_EQN[2] / PLANE_EQN[0]) << " * z + " << (PLANE_EQN[3] / PLANE_EQN[0]) << " = 0" << std::endl;

			const std::vector<bool> &inlierFlags = ransac.getInlierFlags();
			std::cout << "\tIndices of inliers: ";
			size_t idx = 0;
			for (std::vector<bool>::const_iterator cit = inlierFlags.begin(); cit != inlierFlags.end(); ++cit, ++idx)
				if (*cit) std::cout << idx << ", ";
			std::cout << std::endl;
		}
		else
			std::cout << "\tMLESAC failed" << std::endl;
	}
}