<commit_before>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "otbIceViewer.h"
#include "otbDEMHandler.h"

void error_callback(int, const char* description)
{
  std::cerr<<description<<std::endl;
}

int main(int argc, char * argv[])
{
  if(argc < 2)
    {
    std::cerr<<"Usage: "<<argv[0]<<" img1 ... imgN"<<std::endl<<std::endl;

    return EXIT_FAILURE;
    }

  char * demdir = getenv("OTB_DEM_DIR");
  char * geoidfile = getenv("OTB_GEOID_FILE");

  otb::DEMHandler::Pointer demHandler = otb::DEMHandler::Instance();

  if(demdir != NULL)
    {
    std::cout<<"Configuring DEM directory: "<<demdir<<std::endl;
    demHandler->OpenDEMDirectory(demdir);
    }

  if(geoidfile != NULL)
    {
    std::cout<<"Configuring geoid file: "<<geoidfile<<std::endl;
    demHandler->OpenGeoidFile(geoidfile);
    }

  otb::IceViewer::Pointer viewer = otb::IceViewer::New();

  // Initialize viewer
  try
    {
    viewer->Initialize(800,600);
    }
  catch(itk::ExceptionObject& err)
    {
    std::cerr<<"Failed to initialized viewer: "<<err<<std::endl;
    return EXIT_FAILURE;
    }

  for(int i = 1; i<argc;++i)
    {
    try
      {
      viewer->AddImage(argv[i],argv[i]);
      }
    catch(itk::ExceptionObject & err)
      {
      std::cerr<<"Failed to open object as image: "<<err<<std::endl;
      try
        {
        viewer->AddVector(argv[i],argv[i]);
        }
      catch(itk::ExceptionObject & err2)
        {
        std::cerr << "Failed to open object as vector: " << err2 << std::endl;
        std::cerr << "Could not open file " << argv[i] << " as an image or a vector, skipping." << std::endl;
        }
      }
    }

  std::cout<<"Press F1 for help"<<std::endl;

  viewer->Start();

  return EXIT_SUCCESS;
}
<commit_msg>COMP: Fixing coverity issue 1350186 (uncaught std::runtime_exception)<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "otbIceViewer.h"
#include "otbDEMHandler.h"

void error_callback(int, const char* description)
{
  std::cerr<<description<<std::endl;
}

int main(int argc, char * argv[])
{
  if(argc < 2)
    {
    std::cerr<<"Usage: "<<argv[0]<<" img1 ... imgN"<<std::endl<<std::endl;

    return EXIT_FAILURE;
    }

  char * demdir = getenv("OTB_DEM_DIR");
  char * geoidfile = getenv("OTB_GEOID_FILE");

  otb::DEMHandler::Pointer demHandler = otb::DEMHandler::Instance();

  if(demdir != NULL)
    {
    std::cout<<"Configuring DEM directory: "<<demdir<<std::endl;
    demHandler->OpenDEMDirectory(demdir);
    }

  if(geoidfile != NULL)
    {
    std::cout<<"Configuring geoid file: "<<geoidfile<<std::endl;
    demHandler->OpenGeoidFile(geoidfile);
    }

  otb::IceViewer::Pointer viewer = otb::IceViewer::New();

  // Initialize viewer
  try
    {
    viewer->Initialize(800,600);
    }
  catch(itk::ExceptionObject& err)
    {
    std::cerr<<"Failed to initialized viewer: "<<err<<std::endl;
    return EXIT_FAILURE;
    }

  for(int i = 1; i<argc;++i)
    {
    try
      {
      viewer->AddImage(argv[i],argv[i]);
      }
    catch(itk::ExceptionObject & err)
      {
      std::cerr<<"Failed to open object as image: "<<err<<std::endl;
      try
        {
        viewer->AddVector(argv[i],argv[i]);
        }
      catch(itk::ExceptionObject & err2)
        {
        std::cerr << "Failed to open object as vector: " << err2 << std::endl;
        std::cerr << "Could not open file " << argv[i] << " as an image or a vector, skipping." << std::endl;
        }
      }
    catch(std::runtime_error & err)
      {
      std::cerr<<"Runtime error: "<< err.what() <<std::endl;
      return EXIT_FAILURE;
      }
    }

  std::cout<<"Press F1 for help"<<std::endl;

  viewer->Start();

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#pragma once
#include "game.h"

void handleEvent(sf::Keyboard::Key &key, int &scene) {
	switch (key)
	{
	case sf::Keyboard::Left:
		--scene;
		break;
	case sf::Keyboard::Right:
		++scene;
		break;
	default:
		break;
	}
	std::cout << std::to_string(scene) << std::endl;
}

inline void draw(int &scene, sf::Time &t, sf::RenderWindow &window, sf::Texture &texture1, sf::Sprite &sprite1, sf::Texture &texture2, sf::Sprite &sprite2, sf::Font &header, sf::Font &standard, sf::Text &text1, sf::Text &text2, int &lastScene, sf::Sound &sound, sf::SoundBuffer &sound_buffer) {
	window.clear();
	std::string text;
	sf::RectangleShape black;
	int lScene = scene;
	bool playSound = false;
	double t2;
	switch (scene)
	{
	case -1:
		if (scene != lastScene) {
			texture1.loadFromFile("brennendes_Haus.png");
			sprite1.setTexture(texture1);
		}
		window.draw(sprite1);
		break;
	case 0:
		if (t.asMilliseconds() >= 5000) {
			++scene;
			t = t.Zero;
		}

			text1.setFont(header);
			text1.setPosition(window.getSize().x * 0.37f, window.getSize().y * 0.3f);
			text1.setCharacterSize(194);
			text1.setString("1792");
			text2.setFont(header);
			text2.setPosition(window.getSize().x * 0.2f, window.getSize().y * 0.5f);
			text2.setCharacterSize(160);
			text2.setString("Irgendwo in Paris");
			window.draw(text1);
			window.draw(text2);

		break;
	case 1:
		if (t.asMilliseconds() >= 17010) {
			++scene;
			t = t.Zero;
			return;
		}
		if (scene != lastScene) {
			sound_buffer.loadFromFile("sturm.ogg");
			sound.setBuffer(sound_buffer);
			playSound = 1;
			texture1.loadFromFile("brennendes_Haus.png");
			sprite1.setTexture(texture1);
		}
		window.draw(sprite1);
		if (t.asMilliseconds() >= 15000) {
			t2 = t.asSeconds() - 15;
			t2 = 255 * t2 / 2;
			if (t2 > 255) {
				t2 = 255;
			}
			std::cout <<std::to_string(t2)<< std::endl;
			black.setFillColor(sf::Color(0, 0, 0, t2));
			black.setSize(sf::Vector2f(1920, 1080));
			window.draw(black);
		}
		break;
	case 2:
		if (t.asMilliseconds() >= 5000) {
			++scene;
			t = t.Zero;
			return;
		}
		if (scene != lastScene) {
			text1.setFont(header);
			text1.setPosition(window.getSize().x * 0.18f, window.getSize().y * 0.3f);
			text1.setCharacterSize(194);
			text1.setString("10. Januar 1797");
			text2.setFont(header);
			text2.setPosition(window.getSize().x * 0.34f, window.getSize().y * 0.5f);
			text2.setCharacterSize(160);
			text2.setString("Bei Paris");
		}
		window.draw(text1);
		window.draw(text2);
		break;
	case 3:
		if (t.asMilliseconds() >= 10000) {
			++scene;
			t = t.Zero;
			return;
		}
		if (scene != lastScene) {
			text2.setFont(standard);
			text2.setPosition(window.getSize().x * 0.1f, window.getSize().y * 0.1f);
			text2.setCharacterSize(45);

			text = "Hausmutter: \"Elise! Schrei nicht so herum. Andere wollen nachts schlafen!\"\n";
			text += "Elise: \"Bitte Mama, ich werde nicht wieder schreien. Ich versprechs!\"\n";
			text += "Hausmutter: \"Natrlich wirst du das! Aber im Keller!\"\n";
			text += "Elise schluchzt.";
			text2.setString(text);
		}
		window.draw(text2);
		break;
	case 4:
		if (t.asMilliseconds() >= 8010) {
			++scene;
			t = t.Zero;
			return;
		}
		if (scene != lastScene) {
			texture1.loadFromFile("keller_heller.png");

			sprite1.setTexture(texture1);
		}
		window.draw(sprite1);
		if (t.asMilliseconds() >= 6000) {
			t2 = t.asSeconds() - 6;
			t2 = 255 * t2 / 2;
			if (t2 > 255) {
				t2 = 255;
			}
			std::cout << std::to_string(t2) << std::endl;
			black.setFillColor(sf::Color(0, 0, 0, t2));
			black.setSize(sf::Vector2f(1920, 1080));
			window.draw(black);
		}
		break;
	case 5:
		if (scene != lastScene) {
			text2.setFont(standard);
			text2.setPosition(window.getSize().x * 0.05f, window.getSize().y * 0.1f);
			text2.setCharacterSize(45);

			text = "Wieso tut sie mir dass nur an?\n";
			text += "Ich verstehe es nicht!\n";
			text += "Und dieser Traum, er hrt einfach nicht auf mich zu verfolgen...\n";
			text += "Ich wnschte... Nanu? Was ist denn das? Ein rostiger Schmuckkasten?!\n";
			text += "*Knirsch*\n";
			text += "Scheint so als wre im Kasten Platz fr zwei Medaillons, jedoch ist nur eines vorhanden.\n";
			text += "Im inneren des Medaillons ist ein Bild einer Dame, neben ihr ist gerade noch eine Schulter\n";
			text += "zu erkennen, allerdings fehlt die andere Hlfte.\n";
			text += "*Elise betrachtet das Bild nher*\n";
			text += "Was? Das kann nicht. Darf nicht. Kann einfach nicht sein, aber das ist vielleicht doch meine Mutter!";
			text2.setString(text);

		}
		window.draw(text2);
		break;
	case 6:
		if (t.asMilliseconds() >= 8010) {
			++scene;
			t = t.Zero;
			return;
		}
		if (scene != lastScene) {
			texture1.loadFromFile("Waisenhaus.png");

			sprite1.setTexture(texture1);
		}
		window.draw(sprite1);
		if (t.asMilliseconds() >= 6000) {
			t2 = t.asSeconds() - 6;
			t2 = 255 * t2 / 2;
			if (t2 > 255) {
				t2 = 255;
			}
			std::cout << std::to_string(t2) << std::endl;
			black.setFillColor(sf::Color(0, 0, 0, t2));
			black.setSize(sf::Vector2f(1920, 1080));
			window.draw(black);
		}
		break;
	case 7:
		if (scene != lastScene) {
			text2.setFont(standard);
			text2.setPosition(window.getSize().x * 0.05f, window.getSize().y * 0.1f);
			text2.setCharacterSize(45);

			text = "Ich kann einfach nicht mehr. Hier halte ich es keine Sekunde lnger aus.\n";
			text += "Das ist doch kein Leben!\n";
			text += "Maman sagte immer: \"Vis la vie comme tu veux\" (Lebe das Leben, so wie du es mchtest)\n";
			text += "Es reicht mir jetzt, ich breche aus!\n";
			text += "Ich hnge das Medaillon besser um meinen Hals.\n";
			text += "Und nun keinen Mux machen, damit ich nicht erwischt werde.\n";
			text += "Es ist wirklich kalt hier drauen, ich spre meine Finger kaum noch.\n";
			text += "Brrr\n";
			text2.setString(text);

		}
		window.draw(text2);
		break;

	case 8:
		if (t.asMilliseconds() >= 8010) {
			++scene;
			t = t.Zero;
			return;
		}
		if (scene != lastScene) {
			texture1.loadFromFile("gasse_1.png");

			sprite1.setTexture(texture1);
		}
		window.draw(sprite1);
		if (t.asMilliseconds() >= 6000) {
			t2 = t.asSeconds() - 6;
			t2 = 255 * t2 / 2;
			if (t2 > 255) {
				t2 = 255;
			}
			std::cout << std::to_string(t2) << std::endl;
			black.setFillColor(sf::Color(0, 0, 0, t2));
			black.setSize(sf::Vector2f(1920, 1080));
			window.draw(black);
		}
		break;

	case 14:
		t = t.Zero;
		++scene;
		break;
	case 15:
		if (scene != lastScene) {
			t = t.Zero;
			texture1.loadFromFile("Waisenhaus.png");
			sprite1.setTexture(texture1);
		}
		t2 = t.asSeconds();
			if (t2 <= 2) {

				std::cout << std::to_string(t.asSeconds()) << std::endl;
				t2 = 1 - t2 / 4;
				sprite1.setScale(sf::Vector2f(t2, t2));
			}
			else {
				if (t2 != 0.5) {
					t2 = 0.5;
					sprite1.setScale(sf::Vector2f(t2, t2));
				}
			}

		window.draw(sprite1);
		break;
	}
	window.display();
	if (playSound) {
		sound.play();
		playSound = 0;
	}
	lastScene = lScene;
}

int main() {
	sf::RenderWindow window;
	window.create(/*sf::VideoMode::getFullscreenModes().at(0)*/sf::VideoMode(1920,1080), "Textadventure @ Code and Design"/*, sf::Style::Fullscreen*/);
	sf::Texture texture1;
	sf::Sprite sprite1;
	sf::Texture texture2;
	sf::Sprite sprite2;
	sf::Font headline;
	sf::Font stdfont;
	sf::Text text1;
	sf::Text text2;
	sf::Time timer;
	sf::Sound sound;
	sf::SoundBuffer sound_buffer;

	headline.loadFromFile("headline.ttf");
	stdfont.loadFromFile("times.ttf");

	sf::Event event;
	int currentScene = -1;
	int lastScene = -2;
	sf::Clock clock;
	while (window.isOpen()) {
		while (window.pollEvent(event)) {

			if (event.type == sf::Event::Closed) {
				window.close();
			}
			if (event.type == sf::Event::KeyReleased) {
				handleEvent(event.key.code, currentScene);
			}
			if (event.type == sf::Event::MouseButtonReleased) {
				++currentScene;
			}

		}
		timer += clock.restart();
		draw(currentScene, timer, window, texture1, sprite1, texture2, sprite2, headline, stdfont, text1, text2, lastScene, sound, sound_buffer);
	}
	return 0;

}

<commit_msg>Added "Mainmenue"<commit_after>#pragma once
#include "game.h"

void handleEvent(sf::Keyboard::Key &key, int &scene) {
	switch (key)
	{
	case sf::Keyboard::Left:
		--scene;
		break;
	case sf::Keyboard::Right:
		++scene;
		break;
	default:
		break;
	}
	std::cout << std::to_string(scene) << std::endl;
}

inline void draw(int &scene, sf::Time &t, sf::RenderWindow &window, sf::Texture &texture1, sf::Sprite &sprite1, sf::Texture &texture2, sf::Sprite &sprite2, sf::Font &header, sf::Font &standard, sf::Text &text1, sf::Text &text2, int &lastScene, sf::Sound &sound, sf::SoundBuffer &sound_buffer) {
	window.clear();
	std::string text;
	sf::RectangleShape black;
	int lScene = scene;
	bool playSound = false;
	double t2;
	switch (scene)
	{
	case -1:
		if (scene != lastScene) {
			texture1.loadFromFile("brennendes_Haus.png");
			sprite1.setTexture(texture1);
			text1.setFont(header);
			text1.setPosition(window.getSize().x * 0.26f, window.getSize().y * 0.8f);
			text1.setCharacterSize(120);
			text1.setString("Press a key to start!");
		}
		window.draw(sprite1);
		window.draw(text1);
		break;
	case 0:
		if (t.asMilliseconds() >= 5000) {
			++scene;
			t = t.Zero;
		}

			text1.setFont(header);
			text1.setPosition(window.getSize().x * 0.37f, window.getSize().y * 0.3f);
			text1.setCharacterSize(194);
			text1.setString("1792");
			text2.setFont(header);
			text2.setPosition(window.getSize().x * 0.2f, window.getSize().y * 0.5f);
			text2.setCharacterSize(160);
			text2.setString("Irgendwo in Paris");
			window.draw(text1);
			window.draw(text2);

		break;
	case 1:
		if (t.asMilliseconds() >= 17010) {
			++scene;
			t = t.Zero;
			return;
		}
		if (scene != lastScene) {
			sound_buffer.loadFromFile("sturm.ogg");
			sound.setBuffer(sound_buffer);
			playSound = 1;
			texture1.loadFromFile("brennendes_Haus.png");
			sprite1.setTexture(texture1);
		}
		window.draw(sprite1);
		if (t.asMilliseconds() >= 15000) {
			t2 = t.asSeconds() - 15;
			t2 = 255 * t2 / 2;
			if (t2 > 255) {
				t2 = 255;
			}
			std::cout <<std::to_string(t2)<< std::endl;
			black.setFillColor(sf::Color(0, 0, 0, t2));
			black.setSize(sf::Vector2f(1920, 1080));
			window.draw(black);
		}
		break;
	case 2:
		if (t.asMilliseconds() >= 5000) {
			++scene;
			t = t.Zero;
			return;
		}
		if (scene != lastScene) {
			text1.setFont(header);
			text1.setPosition(window.getSize().x * 0.18f, window.getSize().y * 0.3f);
			text1.setCharacterSize(194);
			text1.setString("10. Januar 1797");
			text2.setFont(header);
			text2.setPosition(window.getSize().x * 0.34f, window.getSize().y * 0.5f);
			text2.setCharacterSize(160);
			text2.setString("Bei Paris");
		}
		window.draw(text1);
		window.draw(text2);
		break;
	case 3:
		if (t.asMilliseconds() >= 10000) {
			++scene;
			t = t.Zero;
			return;
		}
		if (scene != lastScene) {
			text2.setFont(standard);
			text2.setPosition(window.getSize().x * 0.1f, window.getSize().y * 0.1f);
			text2.setCharacterSize(45);

			text = "Hausmutter: \"Elise! Schrei nicht so herum. Andere wollen nachts schlafen!\"\n";
			text += "Elise: \"Bitte Mama, ich werde nicht wieder schreien. Ich versprechs!\"\n";
			text += "Hausmutter: \"Natrlich wirst du das! Aber im Keller!\"\n";
			text += "Elise schluchzt.";
			text2.setString(text);
		}
		window.draw(text2);
		break;
	case 4:
		if (t.asMilliseconds() >= 8010) {
			++scene;
			t = t.Zero;
			return;
		}
		if (scene != lastScene) {
			texture1.loadFromFile("keller_heller.png");

			sprite1.setTexture(texture1);
		}
		window.draw(sprite1);
		if (t.asMilliseconds() >= 6000) {
			t2 = t.asSeconds() - 6;
			t2 = 255 * t2 / 2;
			if (t2 > 255) {
				t2 = 255;
			}
			std::cout << std::to_string(t2) << std::endl;
			black.setFillColor(sf::Color(0, 0, 0, t2));
			black.setSize(sf::Vector2f(1920, 1080));
			window.draw(black);
		}
		break;
	case 5:
		if (scene != lastScene) {
			text2.setFont(standard);
			text2.setPosition(window.getSize().x * 0.05f, window.getSize().y * 0.1f);
			text2.setCharacterSize(45);

			text = "Wieso tut sie mir dass nur an?\n";
			text += "Ich verstehe es nicht!\n";
			text += "Und dieser Traum, er hrt einfach nicht auf mich zu verfolgen...\n";
			text += "Ich wnschte... Nanu? Was ist denn das? Ein rostiger Schmuckkasten?!\n";
			text += "*Knirsch*\n";
			text += "Scheint so als wre im Kasten Platz fr zwei Medaillons, jedoch ist nur eines vorhanden.\n";
			text += "Im inneren des Medaillons ist ein Bild einer Dame, neben ihr ist gerade noch eine Schulter\n";
			text += "zu erkennen, allerdings fehlt die andere Hlfte.\n";
			text += "*Elise betrachtet das Bild nher*\n";
			text += "Was? Das kann nicht. Darf nicht. Kann einfach nicht sein, aber das ist vielleicht doch meine Mutter!";
			text2.setString(text);

		}
		window.draw(text2);
		break;
	case 6:
		if (t.asMilliseconds() >= 8010) {
			++scene;
			t = t.Zero;
			return;
		}
		if (scene != lastScene) {
			texture1.loadFromFile("Waisenhaus.png");

			sprite1.setTexture(texture1);
		}
		window.draw(sprite1);
		if (t.asMilliseconds() >= 6000) {
			t2 = t.asSeconds() - 6;
			t2 = 255 * t2 / 2;
			if (t2 > 255) {
				t2 = 255;
			}
			std::cout << std::to_string(t2) << std::endl;
			black.setFillColor(sf::Color(0, 0, 0, t2));
			black.setSize(sf::Vector2f(1920, 1080));
			window.draw(black);
		}
		break;
	case 7:
		if (scene != lastScene) {
			text2.setFont(standard);
			text2.setPosition(window.getSize().x * 0.05f, window.getSize().y * 0.1f);
			text2.setCharacterSize(45);

			text = "Ich kann einfach nicht mehr. Hier halte ich es keine Sekunde lnger aus.\n";
			text += "Das ist doch kein Leben!\n";
			text += "Maman sagte immer: \"Vis la vie comme tu veux\" (Lebe das Leben, so wie du es mchtest)\n";
			text += "Es reicht mir jetzt, ich breche aus!\n";
			text += "Ich hnge das Medaillon besser um meinen Hals.\n";
			text += "Und nun keinen Mux machen, damit ich nicht erwischt werde.\n";
			text += "Es ist wirklich kalt hier drauen, ich spre meine Finger kaum noch.\n";
			text += "Brrr\n";
			text2.setString(text);

		}
		window.draw(text2);
		break;

	case 8:
		if (t.asMilliseconds() >= 8010) {
			++scene;
			t = t.Zero;
			return;
		}
		if (scene != lastScene) {
			texture1.loadFromFile("gasse_1.png");

			sprite1.setTexture(texture1);
		}
		window.draw(sprite1);
		if (t.asMilliseconds() >= 6000) {
			t2 = t.asSeconds() - 6;
			t2 = 255 * t2 / 2;
			if (t2 > 255) {
				t2 = 255;
			}
			std::cout << std::to_string(t2) << std::endl;
			black.setFillColor(sf::Color(0, 0, 0, t2));
			black.setSize(sf::Vector2f(1920, 1080));
			window.draw(black);
		}
		break;

	case 14:
		t = t.Zero;
		++scene;
		break;
	case 15:
		if (scene != lastScene) {
			t = t.Zero;
			texture1.loadFromFile("Waisenhaus.png");
			sprite1.setTexture(texture1);
		}
		t2 = t.asSeconds();
			if (t2 <= 2) {

				std::cout << std::to_string(t.asSeconds()) << std::endl;
				t2 = 1 - t2 / 4;
				sprite1.setScale(sf::Vector2f(t2, t2));
			}
			else {
				if (t2 != 0.5) {
					t2 = 0.5;
					sprite1.setScale(sf::Vector2f(t2, t2));
				}
			}

		window.draw(sprite1);
		break;
	}
	window.display();
	if (playSound) {
		sound.play();
		playSound = 0;
	}
	lastScene = lScene;
}

int main() {
	sf::RenderWindow window;
	window.create(/*sf::VideoMode::getFullscreenModes().at(0)*/sf::VideoMode(1920,1080), "Textadventure @ Code and Design"/*, sf::Style::Fullscreen*/);
	sf::Texture texture1;
	sf::Sprite sprite1;
	sf::Texture texture2;
	sf::Sprite sprite2;
	sf::Font headline;
	sf::Font stdfont;
	sf::Text text1;
	sf::Text text2;
	sf::Time timer;
	sf::Sound sound;
	sf::SoundBuffer sound_buffer;

	headline.loadFromFile("headline.ttf");
	stdfont.loadFromFile("times.ttf");

	sf::Event event;
	int currentScene = -1;
	int lastScene = -2;
	sf::Clock clock;
	while (window.isOpen()) {
		while (window.pollEvent(event)) {

			if (event.type == sf::Event::Closed) {
				window.close();
			}
			if (event.type == sf::Event::KeyReleased) {
				handleEvent(event.key.code, currentScene);
			}
			if (event.type == sf::Event::MouseButtonReleased) {
				++currentScene;
			}

		}
		timer += clock.restart();
		draw(currentScene, timer, window, texture1, sprite1, texture2, sprite2, headline, stdfont, text1, text2, lastScene, sound, sound_buffer);
	}
	return 0;

}

<|endoftext|>


<commit_before>/***********************************************************************************
** MIT License                                                                    **
**                                                                                **
** Copyright (c) 2017 Victor DENIS (victordenis01@gmail.com)                      **
**                                                                                **
** Permission is hereby granted, free of charge, to any person obtaining a copy   **
** of this software and associated documentation files (the "Software"), to deal  **
** in the Software without restriction, including without limitation the rights   **
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell      **
** copies of the Software, and to permit persons to whom the Software is          **
** furnished to do so, subject to the following conditions:                       **
**                                                                                **
** The above copyright notice and this permission notice shall be included in all **
** copies or substantial portions of the Software.                                **
**                                                                                **
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR     **
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,       **
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE    **
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER         **
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,  **
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE  **
** SOFTWARE.                                                                      **
***********************************************************************************/

#include "BrowserWindow.hpp"

#include <QToolTip>

#include <QTimer>

#include "Web/LoadRequest.hpp"
#include "Web/WebPage.hpp"
#include "Web/Tab/WebTab.hpp"
#include "Web/Tab/TabbedWebView.hpp"

#include "Widgets/Tab/TabWidget.hpp"
#include "Widgets/Tab/MainTabBar.hpp"

namespace Sn {

BrowserWindow::BrowserWindow(Application::WindowType type, const QUrl& url) :
	QMainWindow(nullptr),
	m_startUrl(url),
	m_windowType(type)
{
	setAttribute(Qt::WA_DeleteOnClose);
	setAttribute(Qt::WA_DontCreateNativeAncestors);

	setObjectName(QLatin1String("mainwindow"));
	setWindowTitle(tr("Sielo"));
	setProperty("private", Application::instance()->privateBrowsing());

	setupUi();

	QTimer::singleShot(0, this, &BrowserWindow::postLaunch);

}

BrowserWindow::~BrowserWindow()
{
	//TODO: emit window deleted to plugins
}

void BrowserWindow::setStartTab(WebTab* tab)
{
	m_startTab = tab;
}

void BrowserWindow::setStartPage(WebPage* page)
{
	m_startPage = page;
}

void BrowserWindow::currentTabChanged()
{
	TabbedWebView* view{webView()};
	if (!view)
		return;

	setWindowTitle(tr("%1 - Sielo").arg(view->webTab()->title()));

	view->setFocus();
}

TabbedWebView* BrowserWindow::webView() const
{
	return webView(m_tabWidget->currentIndex());
}

TabbedWebView* BrowserWindow::webView(int index) const
{
	WebTab* webTab = qobject_cast<WebTab*>(m_tabWidget->widget(index));
	if (!webTab)
		return 0;

	return webTab->webView();
}

void BrowserWindow::enterHtmlFullScreen()
{
	// Empty
}

void BrowserWindow::bookmarkAllTabs()
{
	// Empty
}

void BrowserWindow::addTab()
{
	m_tabWidget->addView(QUrl(), Application::NTT_SelectedNewEmptyTab, true);
	m_tabWidget->setCurrentTabFresh(true);
}

void BrowserWindow::setupUi()
{
	QWidget* widget{new QWidget(this)};
	widget->setCursor(Qt::ArrowCursor);

	m_layout = new QVBoxLayout(widget);
	m_layout->setSpacing(0);
	m_layout->setContentsMargins(0, 0, 0, 0);

	m_tabWidget = new TabWidget(this, this);

	m_mainSplitter = new QSplitter(this);
	m_mainSplitter->addWidget(m_tabWidget);

	m_layout->addWidget(m_tabWidget->tabBar());
	m_layout->addWidget(m_mainSplitter);

	m_tabWidget->tabBar()->show();

	QPalette palette{QToolTip::palette()};
	QColor color{palette.window().color()};

	color.setAlpha(0);
	palette.setColor(QPalette::Window, color);

	QToolTip::setPalette(palette);

	setMinimumWidth(300);
	//TODO: delete this line when settings will be implements
	resize(1200, 720);
	setCentralWidget(widget);

}

void BrowserWindow::postLaunch()
{
	bool addTab{true};
	QUrl startUrl{};

	show();

	if (!m_startUrl.isEmpty()) {
		startUrl = m_startUrl;
		addTab = true;
	}
	if (m_startTab) {
		addTab = false;
		m_tabWidget->addView(m_startTab);
	}
	if (m_startPage) {
		addTab = false;
		m_tabWidget->addView(QUrl());
		webView()->setPage(m_startPage);
	}

	if (addTab) {
		m_tabWidget->addView(startUrl, Application::NTT_CleanSelectedTabAtEnd);
	}

	if (m_tabWidget->tabBar()->normalTabsCount() <= 0)
		m_tabWidget->addView(m_homePage, Application::NTT_SelectedTabAtEnd);

	//TODO: emit main window created to plugins

	tabWidget()->tabBar()->ensureVisible();
}

}<commit_msg>BrowserWindow: [Add] possibility to use "Ctrl+Shift+T" shortcut<commit_after>/***********************************************************************************
** MIT License                                                                    **
**                                                                                **
** Copyright (c) 2017 Victor DENIS (victordenis01@gmail.com)                      **
**                                                                                **
** Permission is hereby granted, free of charge, to any person obtaining a copy   **
** of this software and associated documentation files (the "Software"), to deal  **
** in the Software without restriction, including without limitation the rights   **
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell      **
** copies of the Software, and to permit persons to whom the Software is          **
** furnished to do so, subject to the following conditions:                       **
**                                                                                **
** The above copyright notice and this permission notice shall be included in all **
** copies or substantial portions of the Software.                                **
**                                                                                **
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR     **
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,       **
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE    **
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER         **
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,  **
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE  **
** SOFTWARE.                                                                      **
***********************************************************************************/

#include "BrowserWindow.hpp"

#include <QToolTip>

#include <QAction>

#include <QTimer>

#include "Web/LoadRequest.hpp"
#include "Web/WebPage.hpp"
#include "Web/Tab/WebTab.hpp"
#include "Web/Tab/TabbedWebView.hpp"

#include "Widgets/Tab/TabWidget.hpp"
#include "Widgets/Tab/MainTabBar.hpp"

namespace Sn {

BrowserWindow::BrowserWindow(Application::WindowType type, const QUrl& url) :
	QMainWindow(nullptr),
	m_startUrl(url),
	m_windowType(type)
{
	setAttribute(Qt::WA_DeleteOnClose);
	setAttribute(Qt::WA_DontCreateNativeAncestors);

	setObjectName(QLatin1String("mainwindow"));
	setWindowTitle(tr("Sielo"));
	setProperty("private", Application::instance()->privateBrowsing());

	setupUi();

	QTimer::singleShot(0, this, &BrowserWindow::postLaunch);

}

BrowserWindow::~BrowserWindow()
{
	//TODO: emit window deleted to plugins
}

void BrowserWindow::setStartTab(WebTab* tab)
{
	m_startTab = tab;
}

void BrowserWindow::setStartPage(WebPage* page)
{
	m_startPage = page;
}

void BrowserWindow::currentTabChanged()
{
	TabbedWebView* view{webView()};
	if (!view)
		return;

	setWindowTitle(tr("%1 - Sielo").arg(view->webTab()->title()));

	view->setFocus();
}

TabbedWebView* BrowserWindow::webView() const
{
	return webView(m_tabWidget->currentIndex());
}

TabbedWebView* BrowserWindow::webView(int index) const
{
	WebTab* webTab = qobject_cast<WebTab*>(m_tabWidget->widget(index));
	if (!webTab)
		return 0;

	return webTab->webView();
}

void BrowserWindow::enterHtmlFullScreen()
{
	// Empty
}

void BrowserWindow::bookmarkAllTabs()
{
	// Empty
}

void BrowserWindow::addTab()
{
	m_tabWidget->addView(QUrl(), Application::NTT_SelectedNewEmptyTab, true);
	m_tabWidget->setCurrentTabFresh(true);
}

void BrowserWindow::setupUi()
{
	QWidget* widget{new QWidget(this)};
	widget->setCursor(Qt::ArrowCursor);

	m_layout = new QVBoxLayout(widget);
	m_layout->setSpacing(0);
	m_layout->setContentsMargins(0, 0, 0, 0);

	m_tabWidget = new TabWidget(this, this);

	m_mainSplitter = new QSplitter(this);
	m_mainSplitter->addWidget(m_tabWidget);

	m_layout->addWidget(m_tabWidget->tabBar());
	m_layout->addWidget(m_mainSplitter);

	m_tabWidget->tabBar()->show();

	QPalette palette{QToolTip::palette()};
	QColor color{palette.window().color()};

	color.setAlpha(0);
	palette.setColor(QPalette::Window, color);

	QToolTip::setPalette(palette);

	setMinimumWidth(300);
	//TODO: delete this line when settings will be implements
	resize(1200, 720);
	setCentralWidget(widget);

}

void BrowserWindow::postLaunch()
{
	bool addTab{true};
	QUrl startUrl{};

	show();

	if (!m_startUrl.isEmpty()) {
		startUrl = m_startUrl;
		addTab = true;
	}
	if (m_startTab) {
		addTab = false;
		m_tabWidget->addView(m_startTab);
	}
	if (m_startPage) {
		addTab = false;
		m_tabWidget->addView(QUrl());
		webView()->setPage(m_startPage);
	}

	if (addTab) {
		m_tabWidget->addView(startUrl, Application::NTT_CleanSelectedTabAtEnd);
	}

	if (m_tabWidget->tabBar()->normalTabsCount() <= 0)
		m_tabWidget->addView(m_homePage, Application::NTT_SelectedTabAtEnd);

	//TODO: emit main window created to plugins

	QAction* action{new QAction(tr("Restore Closed Tab"), this)};
	action->setShortcut(QKeySequence("Ctrl+Shift+T"));
	this->addAction(action);
	connect(action, SIGNAL(triggered()), m_tabWidget, SLOT(restoreClosedTab()));

	tabWidget()->tabBar()->ensureVisible();
}

}<|endoftext|>


<commit_before>//
//  OutputShader.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 27/04/2016.
//  Copyright © 2016 Thomas Harte. All rights reserved.
//

#include "OutputShader.hpp"

#include <stdlib.h>
#include <math.h>

using namespace OpenGL;

namespace {
	const OpenGL::Shader::AttributeBinding bindings[] =
	{
		{"position", 0},
		{"srcCoordinates", 1},
		{"lateral", 2},
		{nullptr}
	};
}

std::unique_ptr<OutputShader> OutputShader::make_shader(const char *fragment_methods, const char *colour_expression, bool use_usampler)
{
	const char *sampler_type = use_usampler ? "usampler2D" : "sampler2D";

	char *vertex_shader;
	asprintf(&vertex_shader,
		"#version 150\n"

		"in vec2 position;"
		"in vec2 srcCoordinates;"
//		"in float lateral;"

		"uniform vec2 boundsOrigin;"
		"uniform vec2 boundsSize;"
		"uniform vec2 positionConversion;"
		"uniform vec2 scanNormal;"
		"uniform %s texID;"

		"out float lateralVarying;"
		"out vec2 srcCoordinatesVarying;"
		"out vec2 iSrcCoordinatesVarying;"

		"void main(void)"
		"{"
			"float laterals[] = float[](0, 0, 1, 0, 1, 1);"
			"float lateral = laterals[gl_VertexID %% 6];"
			"lateralVarying = lateral - 0.5;"

			"ivec2 textureSize = textureSize(texID, 0);"
			"iSrcCoordinatesVarying = srcCoordinates;"
			"srcCoordinatesVarying = vec2(srcCoordinates.x / textureSize.x, (srcCoordinates.y + 0.5) / textureSize.y);"

			"vec2 floatingPosition = (position / positionConversion) + lateral * scanNormal;"
			"vec2 mappedPosition = (floatingPosition - boundsOrigin) / boundsSize;"
			"gl_Position = vec4(mappedPosition.x * 2.0 - 1.0, 1.0 - mappedPosition.y * 2.0, 0.0, 1.0);"
		"}", sampler_type);

	char *fragment_shader;
	asprintf(&fragment_shader,
		"#version 150\n"

		"in float lateralVarying;"
		"in vec2 srcCoordinatesVarying;"
		"in vec2 iSrcCoordinatesVarying;"

		"out vec4 fragColour;"

		"uniform %s texID;"

		"\n%s\n"

		"void main(void)"
		"{"
			"fragColour = vec4(%s, 0.5*cos(lateralVarying));"
		"}",
	sampler_type, fragment_methods, colour_expression);

	std::unique_ptr<OutputShader> result = std::unique_ptr<OutputShader>(new OutputShader(vertex_shader, fragment_shader, bindings));
	free(vertex_shader);
	free(fragment_shader);

	result->boundsSizeUniform			= result->get_uniform_location("boundsSize");
	result->boundsOriginUniform			= result->get_uniform_location("boundsOrigin");
	result->texIDUniform				= result->get_uniform_location("texID");
	result->scanNormalUniform			= result->get_uniform_location("scanNormal");
	result->positionConversionUniform	= result->get_uniform_location("positionConversion");

	return result;
}

void OutputShader::set_output_size(unsigned int output_width, unsigned int output_height, Outputs::CRT::Rect visible_area)
{
	bind();

	GLfloat outputAspectRatioMultiplier = ((float)output_width / (float)output_height) / (4.0f / 3.0f);

	GLfloat bonusWidth = (outputAspectRatioMultiplier - 1.0f) * visible_area.size.width;
	visible_area.origin.x -= bonusWidth * 0.5f * visible_area.size.width;
	visible_area.size.width *= outputAspectRatioMultiplier;

	glUniform2f(boundsOriginUniform, (GLfloat)visible_area.origin.x, (GLfloat)visible_area.origin.y);
	glUniform2f(boundsSizeUniform, (GLfloat)visible_area.size.width, (GLfloat)visible_area.size.height);
}

void OutputShader::set_source_texture_unit(GLenum unit)
{
	bind();
	glUniform1i(texIDUniform, (GLint)(unit - GL_TEXTURE0));
}

void OutputShader::set_timing(unsigned int height_of_display, unsigned int cycles_per_line, unsigned int horizontal_scan_period, unsigned int vertical_scan_period, unsigned int vertical_period_divider)
{
	bind();

	float scan_angle = atan2f(1.0f / (float)height_of_display, 1.0f);
	float scan_normal[] = { -sinf(scan_angle), cosf(scan_angle)};
	float multiplier = (float)cycles_per_line / ((float)height_of_display * (float)horizontal_scan_period);
	scan_normal[0] *= multiplier;
	scan_normal[1] *= multiplier;

	glUniform2f(scanNormalUniform, scan_normal[0], scan_normal[1]);
	glUniform2f(positionConversionUniform, horizontal_scan_period, vertical_scan_period / (unsigned int)vertical_period_divider);
}
<commit_msg>Removed last mentions of 'lateral'.<commit_after>//
//  OutputShader.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 27/04/2016.
//  Copyright © 2016 Thomas Harte. All rights reserved.
//

#include "OutputShader.hpp"

#include <stdlib.h>
#include <math.h>

using namespace OpenGL;

namespace {
	const OpenGL::Shader::AttributeBinding bindings[] =
	{
		{"position", 0},
		{"srcCoordinates", 1},
		{nullptr}
	};
}

std::unique_ptr<OutputShader> OutputShader::make_shader(const char *fragment_methods, const char *colour_expression, bool use_usampler)
{
	const char *sampler_type = use_usampler ? "usampler2D" : "sampler2D";

	char *vertex_shader;
	asprintf(&vertex_shader,
		"#version 150\n"

		"in vec2 position;"
		"in vec2 srcCoordinates;"

		"uniform vec2 boundsOrigin;"
		"uniform vec2 boundsSize;"
		"uniform vec2 positionConversion;"
		"uniform vec2 scanNormal;"
		"uniform %s texID;"

		"out float lateralVarying;"
		"out vec2 srcCoordinatesVarying;"
		"out vec2 iSrcCoordinatesVarying;"

		"void main(void)"
		"{"
			"float laterals[] = float[](0, 0, 1, 0, 1, 1);"
			"float lateral = laterals[gl_VertexID %% 6];"
			"lateralVarying = lateral - 0.5;"

			"ivec2 textureSize = textureSize(texID, 0);"
			"iSrcCoordinatesVarying = srcCoordinates;"
			"srcCoordinatesVarying = vec2(srcCoordinates.x / textureSize.x, (srcCoordinates.y + 0.5) / textureSize.y);"

			"vec2 floatingPosition = (position / positionConversion) + lateral * scanNormal;"
			"vec2 mappedPosition = (floatingPosition - boundsOrigin) / boundsSize;"
			"gl_Position = vec4(mappedPosition.x * 2.0 - 1.0, 1.0 - mappedPosition.y * 2.0, 0.0, 1.0);"
		"}", sampler_type);

	char *fragment_shader;
	asprintf(&fragment_shader,
		"#version 150\n"

		"in float lateralVarying;"
		"in vec2 srcCoordinatesVarying;"
		"in vec2 iSrcCoordinatesVarying;"

		"out vec4 fragColour;"

		"uniform %s texID;"

		"\n%s\n"

		"void main(void)"
		"{"
			"fragColour = vec4(%s, 0.5*cos(lateralVarying));"
		"}",
	sampler_type, fragment_methods, colour_expression);

	std::unique_ptr<OutputShader> result = std::unique_ptr<OutputShader>(new OutputShader(vertex_shader, fragment_shader, bindings));
	free(vertex_shader);
	free(fragment_shader);

	result->boundsSizeUniform			= result->get_uniform_location("boundsSize");
	result->boundsOriginUniform			= result->get_uniform_location("boundsOrigin");
	result->texIDUniform				= result->get_uniform_location("texID");
	result->scanNormalUniform			= result->get_uniform_location("scanNormal");
	result->positionConversionUniform	= result->get_uniform_location("positionConversion");

	return result;
}

void OutputShader::set_output_size(unsigned int output_width, unsigned int output_height, Outputs::CRT::Rect visible_area)
{
	bind();

	GLfloat outputAspectRatioMultiplier = ((float)output_width / (float)output_height) / (4.0f / 3.0f);

	GLfloat bonusWidth = (outputAspectRatioMultiplier - 1.0f) * visible_area.size.width;
	visible_area.origin.x -= bonusWidth * 0.5f * visible_area.size.width;
	visible_area.size.width *= outputAspectRatioMultiplier;

	glUniform2f(boundsOriginUniform, (GLfloat)visible_area.origin.x, (GLfloat)visible_area.origin.y);
	glUniform2f(boundsSizeUniform, (GLfloat)visible_area.size.width, (GLfloat)visible_area.size.height);
}

void OutputShader::set_source_texture_unit(GLenum unit)
{
	bind();
	glUniform1i(texIDUniform, (GLint)(unit - GL_TEXTURE0));
}

void OutputShader::set_timing(unsigned int height_of_display, unsigned int cycles_per_line, unsigned int horizontal_scan_period, unsigned int vertical_scan_period, unsigned int vertical_period_divider)
{
	bind();

	float scan_angle = atan2f(1.0f / (float)height_of_display, 1.0f);
	float scan_normal[] = { -sinf(scan_angle), cosf(scan_angle)};
	float multiplier = (float)cycles_per_line / ((float)height_of_display * (float)horizontal_scan_period);
	scan_normal[0] *= multiplier;
	scan_normal[1] *= multiplier;

	glUniform2f(scanNormalUniform, scan_normal[0], scan_normal[1]);
	glUniform2f(positionConversionUniform, horizontal_scan_period, vertical_scan_period / (unsigned int)vertical_period_divider);
}
<|endoftext|>


<commit_before>#include "crunch.h"

#include <list>
#include <pthread.h>
#include <time.h>

#include <raytracer/raytracer.h>
#include <platform.h>

pthread_mutex_t g_iDataMutex;

void CAOGenerator::RaytraceSceneFromPosition(raytrace::CRaytracer* pTracer, Vector vecUVPosition, Vector vecNormal, CConversionMeshInstance* pMeshInstance, CConversionFace* pFace, size_t iTexel)
{
	// Build rotation matrix
	Matrix4x4 m;
	m.SetOrientation(vecNormal);

	// Turn it sideways so that pitch 90 is up, for more uniform sampling
	Matrix4x4 m2;
	m2.SetRotation(EAngle(0, -90, 0));

	m *= m2;

	float flHits = 0;
	float flTotalHits = 0;

	for (size_t x = 0; x < m_iSamples/2; x++)
	{
		float flRandom = 0;
		if (m_bRandomize)
			flRandom = RemapVal((float)(rand()%10000), 0, 10000.0f, -0.5, 0.5);

		float flPitch = RemapVal(cos(RemapVal((float)x+flRandom, 0, (float)m_iSamples/2, 0, M_PI/2)), 0, 1, 90, 0);

		float flWeight = sin(flPitch * M_PI/180);

		for (size_t y = 0; y <= m_iSamples; y++)
		{
			flRandom = 0;
			if (m_bRandomize)
				flRandom = RemapVal((float)(rand()%10000), 0, 10000.0f, -0.5, 0.5);

			float flYaw = RemapVal((float)y+flRandom, 0, (float)m_iSamples, -180, 180);

			Vector vecDir = AngleVector(EAngle(flPitch, flYaw, 0));

			// Transform relative to the triangle's normal
			Vector vecRay = m * vecDir;

			//RenderSceneFromPosition(vecUVPosition, vecRay, pFace);

			flTotalHits += flWeight;

			Vector vecHit;
			if (pTracer->Raytrace(Ray(vecUVPosition + pFace->GetNormal()*0.01f, vecRay), &vecHit))
			{
				float flDistance = (vecHit - vecUVPosition).Length();
				if (m_flRayFalloff < 0)
					flHits += flWeight;
				else
					flHits += flWeight * (1/pow(2, flDistance/m_flRayFalloff));
			}
			else if (m_bGroundOcclusion && vecRay.y < 0)
			{
				// The following math is basically a plane-ray intersection algorithm,
				// with shortcuts made for the assumption of an infinite plane facing straight up.

				Vector n = Vector(0,1,0);

				float a = -(vecUVPosition.y - pMeshInstance->m_pParent->m_oExtends.m_vecMins.y);
				float b = vecRay.y;

				float flDistance = a/b;

				if (flDistance < 1e-4f || m_flRayFalloff < 0)
					flHits += flWeight;
				else
					flHits += flWeight * (1/pow(2, flDistance/m_flRayFalloff));
			}
		}
	}

	// One last ray directly up, it is skipped in the above loop so it's not done 10 times.
	Vector vecDir = AngleVector(EAngle(90, 0, 0));

	// Transform relative to the triangle's normal
	Vector vecRay = m * vecDir;

	//RenderSceneFromPosition(vecUVPosition, vecRay, pFace);

	flTotalHits++;

	Vector vecHit;
	if (pTracer->Raytrace(Ray(vecUVPosition + pFace->GetNormal()*0.01f, vecRay), &vecHit))
	{
		float flDistance = (vecHit - vecUVPosition).Length();
		if (m_flRayFalloff < 0)
			flHits += 1;
		else
			flHits += (1/pow(2, flDistance/m_flRayFalloff));
	}
	else if (m_bGroundOcclusion && vecRay.y < 0)
	{
		// The following math is basically a plane-ray intersection algorithm,
		// with shortcuts made for the assumption of an infinite plane facing straight up.

		Vector n = Vector(0,1,0);

		float a = -(vecUVPosition.y - pMeshInstance->m_pParent->m_oExtends.m_vecMins.y);
		float b = vecRay.y;

		float flDistance = a/b;

		if (flDistance < 1e-4f || m_flRayFalloff < 0)
			flHits += 1;
		else
			flHits += (1/pow(2, flDistance/m_flRayFalloff));
	}

	float flShadowValue = 1 - ((float)flHits / (float)flTotalHits);

	// Mutex may be dead, try to bail before.
	if (m_bStopGenerating)
		return;

	if (GetNumberOfProcessors() > 1)
	{
		// Keep all locking and unlocking in one branch to prevent processor prediction miss problems.
		// I saw it in some presentation somewhere.
		pthread_mutex_lock(&g_iDataMutex);
		m_avecShadowValues[iTexel] += Vector(flShadowValue, flShadowValue, flShadowValue);
		pthread_mutex_unlock(&g_iDataMutex);
	}
	else
		m_avecShadowValues[iTexel] += Vector(flShadowValue, flShadowValue, flShadowValue);
}

typedef struct
{
	raytrace::CRaytracer*		pTracer;
	Vector						vecUVPosition;
	Vector						vecNormal;
	CConversionMeshInstance*	pMeshInstance;
	CConversionFace*			pFace;
	size_t						iTexel;
} thread_job_t;

typedef struct
{
	pthread_t					iThread;
	CAOGenerator*				pGenerator;
	bool						bQuitWhenDone;
	bool						bDone;
} thread_data_t;

std::vector<thread_data_t> g_aThreads;
std::list<thread_job_t> g_lJobs;
pthread_mutex_t g_iJobsMutex;
size_t g_iJobsGiven = 0;

void RaytraceThreadMain(void* pData)
{
	thread_data_t* pThread = (thread_data_t*)pData;
	while (true)
	{
		pthread_mutex_lock(&g_iJobsMutex);
		if (!g_lJobs.size())
		{
			pthread_mutex_unlock(&g_iJobsMutex);

			if (pThread->bQuitWhenDone)
			{
				pThread->bDone = true;
				pthread_exit(NULL);
				return;
			}
			else
			{
				// Give the main thread a chance to render and whatnot.
				SleepMS(1);
				continue;
			}
		}

		// Copy so we can pop it.
		thread_job_t oThreadJob = g_lJobs.front();
		g_lJobs.pop_front();

		pthread_mutex_unlock(&g_iJobsMutex);

		pThread->pGenerator->RaytraceSceneFromPosition(oThreadJob.pTracer, oThreadJob.vecUVPosition, oThreadJob.vecNormal, oThreadJob.pMeshInstance, oThreadJob.pFace, oThreadJob.iTexel);

		// Give the main thread a chance to render and whatnot.
		SleepMS(1);

		if (pThread->pGenerator->IsStopped())
		{
			pThread->bDone = true;
			pthread_exit(NULL);
			return;
		}
	}
}

void CAOGenerator::RaytraceSetupThreads()
{
	if (GetNumberOfProcessors() == 1)
		return;

	pthread_mutex_init(&g_iDataMutex, NULL);
	pthread_mutex_init(&g_iJobsMutex, NULL);

	g_iJobsGiven = 0;

	// Insert all first so that reallocations are all done before we pass the pointers to the threads.
	g_aThreads.insert(g_aThreads.begin(), GetNumberOfProcessors(), thread_data_t());

	for (size_t i = 0; i < GetNumberOfProcessors(); i++)
	{
		thread_data_t* pThread = &g_aThreads[i];

		pThread->pGenerator = this;
		pThread->bQuitWhenDone = false;
		pThread->bDone = false;

		pthread_create(&pThread->iThread, NULL, (void *(*) (void *))&RaytraceThreadMain, (void*)pThread);
	}
}

void CAOGenerator::RaytraceCleanupThreads()
{
	if (GetNumberOfProcessors() == 1)
		return;

	// If there are no threads then we've already cleaned up, don't do it twice.
	if (!g_aThreads.size())
		return;

	for (size_t i = 0; i < g_aThreads.size(); i++)
	{
		thread_data_t* pThread = &g_aThreads[i];

		pthread_detach(pThread->iThread);
	}

	pthread_mutex_destroy(&g_iDataMutex);
	pthread_mutex_destroy(&g_iJobsMutex);

	g_aThreads.clear();
}

void CAOGenerator::RaytraceSceneMultithreaded(raytrace::CRaytracer* pTracer, Vector vecUVPosition, Vector vecNormal, CConversionMeshInstance* pMeshInstance, CConversionFace* pFace, size_t iTexel)
{
	if (GetNumberOfProcessors() == 1)
	{
		RaytraceSceneFromPosition(pTracer, vecUVPosition, vecNormal, pMeshInstance, pFace, iTexel);
		return;
	}

	pthread_mutex_lock(&g_iJobsMutex);

	g_lJobs.push_back(thread_job_t());
	thread_job_t* pJob = &g_lJobs.back();
	pJob->pTracer = pTracer;
	pJob->vecUVPosition = vecUVPosition;
	pJob->vecNormal = vecNormal;
	pJob->pMeshInstance = pMeshInstance;
	pJob->pFace = pFace;
	pJob->iTexel = iTexel;

	pthread_mutex_unlock(&g_iJobsMutex);

	g_iJobsGiven++;
}

void CAOGenerator::RaytraceJoinThreads()
{
	if (GetNumberOfProcessors() == 1)
		return;

	// Doesn't really join the threads per se, just signals for them to quit and then waits for them to be done
	// while calling work progress updates so the user can see what's happening.

	for (size_t i = 0; i < g_aThreads.size(); i++)
		g_aThreads[i].bQuitWhenDone = true;

	if (m_pWorkListener)
		m_pWorkListener->SetAction(L"Rendering", g_iJobsGiven);

	while (true)
	{
		bool bDone = true;
		for (size_t t = 0; t < g_aThreads.size(); t++)
		{
			if (!g_aThreads[t].bDone)
				bDone = false;
		}

		if (bDone)
			return;

		if (m_pWorkListener)
			m_pWorkListener->WorkProgress(g_iJobsGiven - g_lJobs.size());

		if (m_bStopGenerating)
		{
			RaytraceCleanupThreads();
			return;
		}
	}
}
<commit_msg>Prevent some threads-related crashes.<commit_after>#include "crunch.h"

#include <list>
#include <pthread.h>
#include <time.h>

#include <raytracer/raytracer.h>
#include <platform.h>

pthread_mutex_t g_iDataMutex;

void CAOGenerator::RaytraceSceneFromPosition(raytrace::CRaytracer* pTracer, Vector vecUVPosition, Vector vecNormal, CConversionMeshInstance* pMeshInstance, CConversionFace* pFace, size_t iTexel)
{
	// Build rotation matrix
	Matrix4x4 m;
	m.SetOrientation(vecNormal);

	// Turn it sideways so that pitch 90 is up, for more uniform sampling
	Matrix4x4 m2;
	m2.SetRotation(EAngle(0, -90, 0));

	m *= m2;

	float flHits = 0;
	float flTotalHits = 0;

	for (size_t x = 0; x < m_iSamples/2; x++)
	{
		float flRandom = 0;
		if (m_bRandomize)
			flRandom = RemapVal((float)(rand()%10000), 0, 10000.0f, -0.5, 0.5);

		float flPitch = RemapVal(cos(RemapVal((float)x+flRandom, 0, (float)m_iSamples/2, 0, M_PI/2)), 0, 1, 90, 0);

		float flWeight = sin(flPitch * M_PI/180);

		for (size_t y = 0; y <= m_iSamples; y++)
		{
			flRandom = 0;
			if (m_bRandomize)
				flRandom = RemapVal((float)(rand()%10000), 0, 10000.0f, -0.5, 0.5);

			float flYaw = RemapVal((float)y+flRandom, 0, (float)m_iSamples, -180, 180);

			Vector vecDir = AngleVector(EAngle(flPitch, flYaw, 0));

			// Transform relative to the triangle's normal
			Vector vecRay = m * vecDir;

			//RenderSceneFromPosition(vecUVPosition, vecRay, pFace);

			flTotalHits += flWeight;

			Vector vecHit;
			if (pTracer->Raytrace(Ray(vecUVPosition + pFace->GetNormal()*0.01f, vecRay), &vecHit))
			{
				float flDistance = (vecHit - vecUVPosition).Length();
				if (m_flRayFalloff < 0)
					flHits += flWeight;
				else
					flHits += flWeight * (1/pow(2, flDistance/m_flRayFalloff));
			}
			else if (m_bGroundOcclusion && vecRay.y < 0)
			{
				// The following math is basically a plane-ray intersection algorithm,
				// with shortcuts made for the assumption of an infinite plane facing straight up.

				Vector n = Vector(0,1,0);

				float a = -(vecUVPosition.y - pMeshInstance->m_pParent->m_oExtends.m_vecMins.y);
				float b = vecRay.y;

				float flDistance = a/b;

				if (flDistance < 1e-4f || m_flRayFalloff < 0)
					flHits += flWeight;
				else
					flHits += flWeight * (1/pow(2, flDistance/m_flRayFalloff));
			}
		}
	}

	// One last ray directly up, it is skipped in the above loop so it's not done 10 times.
	Vector vecDir = AngleVector(EAngle(90, 0, 0));

	// Transform relative to the triangle's normal
	Vector vecRay = m * vecDir;

	//RenderSceneFromPosition(vecUVPosition, vecRay, pFace);

	flTotalHits++;

	Vector vecHit;
	if (pTracer->Raytrace(Ray(vecUVPosition + pFace->GetNormal()*0.01f, vecRay), &vecHit))
	{
		float flDistance = (vecHit - vecUVPosition).Length();
		if (m_flRayFalloff < 0)
			flHits += 1;
		else
			flHits += (1/pow(2, flDistance/m_flRayFalloff));
	}
	else if (m_bGroundOcclusion && vecRay.y < 0)
	{
		// The following math is basically a plane-ray intersection algorithm,
		// with shortcuts made for the assumption of an infinite plane facing straight up.

		Vector n = Vector(0,1,0);

		float a = -(vecUVPosition.y - pMeshInstance->m_pParent->m_oExtends.m_vecMins.y);
		float b = vecRay.y;

		float flDistance = a/b;

		if (flDistance < 1e-4f || m_flRayFalloff < 0)
			flHits += 1;
		else
			flHits += (1/pow(2, flDistance/m_flRayFalloff));
	}

	float flShadowValue = 1 - ((float)flHits / (float)flTotalHits);

	// Mutex may be dead, try to bail before.
	if (m_bStopGenerating)
		return;

	if (GetNumberOfProcessors() > 1)
	{
		// Keep all locking and unlocking in one branch to prevent processor prediction miss problems.
		// I saw it in some presentation somewhere.
		pthread_mutex_lock(&g_iDataMutex);
		m_avecShadowValues[iTexel] += Vector(flShadowValue, flShadowValue, flShadowValue);
		pthread_mutex_unlock(&g_iDataMutex);
	}
	else
		m_avecShadowValues[iTexel] += Vector(flShadowValue, flShadowValue, flShadowValue);
}

typedef struct
{
	raytrace::CRaytracer*		pTracer;
	Vector						vecUVPosition;
	Vector						vecNormal;
	CConversionMeshInstance*	pMeshInstance;
	CConversionFace*			pFace;
	size_t						iTexel;
} thread_job_t;

typedef struct
{
	pthread_t					iThread;
	CAOGenerator*				pGenerator;
	bool						bQuitWhenDone;
	bool						bDone;
} thread_data_t;

std::vector<thread_data_t> g_aThreads;
std::list<thread_job_t> g_lJobs;
pthread_mutex_t g_iJobsMutex;
size_t g_iJobsGiven = 0;

void RaytraceThreadMain(void* pData)
{
	thread_data_t* pThread = (thread_data_t*)pData;
	while (true)
	{
		if (pThread->pGenerator->IsStopped())
		{
			pThread->bDone = true;
			pthread_exit(NULL);
			return;
		}

		pthread_mutex_lock(&g_iJobsMutex);
		if (!g_lJobs.size())
		{
			pthread_mutex_unlock(&g_iJobsMutex);

			if (pThread->bQuitWhenDone)
			{
				pThread->bDone = true;
				pthread_exit(NULL);
				return;
			}
			else
			{
				// Give the main thread a chance to render and whatnot.
				SleepMS(1);
				continue;
			}
		}

		// Copy so we can pop it.
		thread_job_t oThreadJob = g_lJobs.front();
		g_lJobs.pop_front();

		pthread_mutex_unlock(&g_iJobsMutex);

		pThread->pGenerator->RaytraceSceneFromPosition(oThreadJob.pTracer, oThreadJob.vecUVPosition, oThreadJob.vecNormal, oThreadJob.pMeshInstance, oThreadJob.pFace, oThreadJob.iTexel);

		// Give the main thread a chance to render and whatnot.
		SleepMS(1);
	}
}

void CAOGenerator::RaytraceSetupThreads()
{
	if (GetNumberOfProcessors() == 1)
		return;

	pthread_mutex_init(&g_iDataMutex, NULL);
	pthread_mutex_init(&g_iJobsMutex, NULL);

	g_iJobsGiven = 0;

	// Insert all first so that reallocations are all done before we pass the pointers to the threads.
	g_aThreads.insert(g_aThreads.begin(), GetNumberOfProcessors(), thread_data_t());

	for (size_t i = 0; i < GetNumberOfProcessors(); i++)
	{
		thread_data_t* pThread = &g_aThreads[i];

		pThread->pGenerator = this;
		pThread->bQuitWhenDone = false;
		pThread->bDone = false;

		pthread_create(&pThread->iThread, NULL, (void *(*) (void *))&RaytraceThreadMain, (void*)pThread);
	}
}

void CAOGenerator::RaytraceCleanupThreads()
{
	if (GetNumberOfProcessors() == 1)
		return;

	// If there are no threads then we've already cleaned up, don't do it twice.
	if (!g_aThreads.size())
		return;

	for (size_t i = 0; i < g_aThreads.size(); i++)
	{
		thread_data_t* pThread = &g_aThreads[i];

		pthread_detach(pThread->iThread);
	}

	pthread_mutex_destroy(&g_iDataMutex);
	pthread_mutex_destroy(&g_iJobsMutex);

	g_aThreads.clear();
	g_lJobs.clear();
}

void CAOGenerator::RaytraceSceneMultithreaded(raytrace::CRaytracer* pTracer, Vector vecUVPosition, Vector vecNormal, CConversionMeshInstance* pMeshInstance, CConversionFace* pFace, size_t iTexel)
{
	if (GetNumberOfProcessors() == 1)
	{
		RaytraceSceneFromPosition(pTracer, vecUVPosition, vecNormal, pMeshInstance, pFace, iTexel);
		return;
	}

	pthread_mutex_lock(&g_iJobsMutex);

	g_lJobs.push_back(thread_job_t());
	thread_job_t* pJob = &g_lJobs.back();
	pJob->pTracer = pTracer;
	pJob->vecUVPosition = vecUVPosition;
	pJob->vecNormal = vecNormal;
	pJob->pMeshInstance = pMeshInstance;
	pJob->pFace = pFace;
	pJob->iTexel = iTexel;

	pthread_mutex_unlock(&g_iJobsMutex);

	g_iJobsGiven++;
}

void CAOGenerator::RaytraceJoinThreads()
{
	if (GetNumberOfProcessors() == 1)
		return;

	// Doesn't really join the threads per se, just signals for them to quit and then waits for them to be done
	// while calling work progress updates so the user can see what's happening.

	for (size_t i = 0; i < g_aThreads.size(); i++)
		g_aThreads[i].bQuitWhenDone = true;

	if (m_pWorkListener)
		m_pWorkListener->SetAction(L"Rendering", g_iJobsGiven);

	while (true)
	{
		bool bDone = true;
		for (size_t t = 0; t < g_aThreads.size(); t++)
		{
			if (!g_aThreads[t].bDone)
				bDone = false;
		}

		if (bDone)
			return;

		if (m_pWorkListener)
			m_pWorkListener->WorkProgress(g_iJobsGiven - g_lJobs.size());

		if (m_bStopGenerating)
		{
			RaytraceCleanupThreads();
			return;
		}
	}
}
<|endoftext|>


<commit_before>#include "GameInstanceServer.h"
#include "../networking/peermanager.h"
#include "../gamecommon/PhysicsEngine.h"

#include <random>

#define MINPLAYERS 1

BEGIN_NETTORAWMESSAGE_QCONVERT(RequestChunkData)
out << coord;
END_NETTORAWMESSAGE_QCONVERT()
BEGIN_RAWTONETMESSAGE_QCONVERT(RequestChunkData)
in >> coord;
END_RAWTONETMESSAGE_QCONVERT()
REGISTER_NETMESSAGE(RequestChunkData)

BEGIN_NETTORAWMESSAGE_QCONVERT(StopChunkTracking)
out << coord;
END_NETTORAWMESSAGE_QCONVERT()
BEGIN_RAWTONETMESSAGE_QCONVERT(StopChunkTracking)
in >> coord;
END_RAWTONETMESSAGE_QCONVERT();
REGISTER_NETMESSAGE(StopChunkTracking)

GameInstanceServer::GameInstanceServer(const std::string &name) :
m_physicsEngine(new PhysicsEngine),
m_name(name)
{
    // nop
    m_gameInfo = std::make_shared<GameInfoServer>(0, this);
    m_waitingForPlayers = true;
}

GameInstanceServer::~GameInstanceServer()
{
}

std::string GameInstanceServer::name() const
{
    return m_name;
}

bool GameInstanceServer::unknownObjectIdMessage(const GameMessage::const_pointer& msg, MessagePeer* sender)
{
    // The creation of objects on the client side is not allowed.

    std::cerr << "WTF? GameInstanceServer just received a message from an object with non-existing objectId[" << msg->objectId << "]\n";
    return false;
}

void GameInstanceServer::connectLocallyTo(MessagePeer* buddy, bool recursive /*= true*/)
{
    // we have got a new client! Create a SpaceShip just for him
    GameMessagePeer::connectLocallyTo(buddy, recursive);

    SpaceShipServer::pointer hisShip{
        new SpaceShipServer(osg::Vec3f(), osg::Quat(0, osg::Vec3f(1, 0, 0)), RemotePeersManager::getManager()->getPeersId(buddy), this, m_physicsEngine) };

    //GameMessage::pointer constructItMsg = m_asteroidField->creationMessage();
    //buddy->send(constructItMsg);
    GameMessage::pointer constructItMsg;
    for (std::pair<MessagePeer*, SpaceShipServer::pointer> aShip : m_peerSpaceShips)
    {
        constructItMsg = aShip.second->creationMessage();
        buddy->send(constructItMsg);
    }
    broadcastLocally(hisShip->creationMessage());
    m_peerSpaceShips.insert(std::make_pair(buddy, hisShip));

    GameMessage::pointer constructGameInfoMsg = m_gameInfo->creationMessage();
    buddy->send(constructGameInfoMsg);

    if (m_peerSpaceShips.size() >= MINPLAYERS && m_waitingForPlayers)
    {
        m_waitingForPlayers = false;
        newRound();
    }
}

void GameInstanceServer::newRound()
{
    std::random_device randDevice;
    //float range = m_asteroidField->getCubeSideLength();
    float range = 16.0; // todo: new range calculation?
    float maxRand = randDevice.max();

    osg::Vec3f startingPoint = osg::Vec3f(
        range*randDevice() / maxRand,
        range*randDevice() / maxRand,
        range*randDevice() / maxRand);
    osg::Vec3f finishArea = osg::Vec3f(
        range*randDevice() / maxRand,
        range*randDevice() / maxRand,
        range*randDevice() / maxRand);
    m_gameInfo->setObjective(startingPoint, finishArea, 1);

    GameMessage::pointer msg = m_gameInfo->objectiveMessage();
    btTransform t;
    for (std::map<MessagePeer*, SpaceShipServer::pointer>::iterator peerSpaceShip = m_peerSpaceShips.begin(); peerSpaceShip != m_peerSpaceShips.end(); ++peerSpaceShip)
    {
        //set ship positions to starting point
        osg::Vec3f v1 = osg::Vec3f(0, 0, 1), v2 = startingPoint - finishArea;
        osg::Vec3f a = v1 ^ v2;
        float w = sqrt(v1.length2() * v2.length2()) + v1*v2;
        btQuaternion q = btQuaternion(a.x(), a.y(), a.z(), w).normalize();
        t.setRotation(q);
        t.setOrigin(btVector3(startingPoint.x(), startingPoint.y(), startingPoint.z()));

        unsigned int physId = peerSpaceShip->second->getPhysicsId();

        m_physicsEngine->setShipTransformation(physId, t);

        //inform clients about new objective
        MessagePeer* buddy = peerSpaceShip->first;
        buddy->send(msg);

    }
}

void GameInstanceServer::disconnectLocallyFrom(MessagePeer* buddy, bool recursive /*= true*/)
{

    GameMessagePeer::disconnectLocallyFrom(buddy, recursive);

    SpaceShipServer::pointer shipToRemove = m_peerSpaceShips.at(buddy);
    NetRemoveGameObjectMessage::pointer removeMessage{ new NetRemoveGameObjectMessage };
    removeMessage->objectId = shipToRemove->getObjectId();
    broadcastLocally(removeMessage);

    m_peerSpaceShips.erase(buddy);

    if (m_peerSpaceShips.size() < MINPLAYERS)
    {
        m_waitingForPlayers = true;
    }
}

void GameInstanceServer::physicsTick(float timeInterval)
{
    m_physicsEngine->physicsTick(timeInterval);
    checkForEndround();
}

void GameInstanceServer::checkForEndround()
{
    bool someShipEnteredFinishArea = false;
    for (std::map<MessagePeer*, SpaceShipServer::pointer>::iterator peerSpaceShip = m_peerSpaceShips.begin(); peerSpaceShip != m_peerSpaceShips.end(); ++peerSpaceShip)
    {
        unsigned int physId = peerSpaceShip->second->getPhysicsId();
        osg::Vec3f pos = m_physicsEngine->getShipPosition(physId);
        if ( m_gameInfo->shipInFinishArea(pos) )
        {
            someShipEnteredFinishArea = true;
            break;
        }
    }
    if (someShipEnteredFinishArea)
    {
        //todo. update the players scores
        newRound();
    }
}

GameInstanceServer::ChunkCoordinates GameInstanceServer::positionToChunk(const osg::Vec3f& pos)
{
    return ChunkCoordinates(std::floor(pos.x() / 16.0),
        std::floor(pos.y() / 16.0),
        std::floor(pos.z() / 16.0));
}

bool GameInstanceServer::takeMessage(const NetMessage::const_pointer& msg, MessagePeer* peer)
{
    if (msg->gettype() == NetRequestChunkDataMessage::type)
    {
        NetRequestChunkDataMessage::const_pointer realMsg = msg->as<NetRequestChunkDataMessage>();
        osg::Vec3i chunkCoord = realMsg->coord;
        // A client has requested data about the chunk.
        // First look if we have it in our dictionary
        if (m_universe.count(chunkCoord) == 0)
        {
            // The chunk doesn't exist yet, generate it
            ServerChunkData newChunk;
            newChunk.m_asteroidField = std::make_shared<AsteroidFieldChunkServer>(200, 16, 0, chunkCoord, this, m_physicsEngine.get());
            m_universe.insert(std::make_pair(chunkCoord, newChunk));
        }

        ServerChunkData& myChunk = m_universe[chunkCoord];
        NetMessage::pointer reply = myChunk.m_asteroidField->creationMessage();
        myChunk.m_observers.push_back(peer);

        peer->send(reply, this);
        return true;
    }
    else if (msg->gettype() == NetStopChunkTrackingMessage::type)
    {
        NetRequestChunkDataMessage::const_pointer realMsg = msg->as<NetRequestChunkDataMessage>();
        osg::Vec3i chunkCoord = realMsg->coord;

        if (m_universe.count(chunkCoord) == 0)
            return false;
        ServerChunkData& myChunk = m_universe[chunkCoord];

        auto erasePosition = std::find(myChunk.m_observers.cbegin(), myChunk.m_observers.cend(), peer);
        if (erasePosition == myChunk.m_observers.cend())
            return false;

        myChunk.m_observers.erase(erasePosition);
        if (myChunk.m_observers.empty())
        {
            m_universe.erase(chunkCoord);
        }
        return true;
    }
    return GameMessagePeer::takeMessage(msg, peer);
}

osg::Vec3f GameInstanceServer::chunkToPosition(const osg::Vec3i& pos)
{
    return osg::Vec3f(pos.x() * 16.0, pos.y()*16.0, pos.z()*16.0);
}

<commit_msg>Remove untracked chunks on client disconnection event.<commit_after>#include "GameInstanceServer.h"
#include "../networking/peermanager.h"
#include "../gamecommon/PhysicsEngine.h"

#include <random>

#define MINPLAYERS 1

BEGIN_NETTORAWMESSAGE_QCONVERT(RequestChunkData)
out << coord;
END_NETTORAWMESSAGE_QCONVERT()
BEGIN_RAWTONETMESSAGE_QCONVERT(RequestChunkData)
in >> coord;
END_RAWTONETMESSAGE_QCONVERT()
REGISTER_NETMESSAGE(RequestChunkData)

BEGIN_NETTORAWMESSAGE_QCONVERT(StopChunkTracking)
out << coord;
END_NETTORAWMESSAGE_QCONVERT()
BEGIN_RAWTONETMESSAGE_QCONVERT(StopChunkTracking)
in >> coord;
END_RAWTONETMESSAGE_QCONVERT();
REGISTER_NETMESSAGE(StopChunkTracking)

GameInstanceServer::GameInstanceServer(const std::string &name) :
m_physicsEngine(new PhysicsEngine),
m_name(name)
{
    // nop
    m_gameInfo = std::make_shared<GameInfoServer>(0, this);
    m_waitingForPlayers = true;
}

GameInstanceServer::~GameInstanceServer()
{
}

std::string GameInstanceServer::name() const
{
    return m_name;
}

bool GameInstanceServer::unknownObjectIdMessage(const GameMessage::const_pointer& msg, MessagePeer* sender)
{
    // The creation of objects on the client side is not allowed.

    std::cerr << "WTF? GameInstanceServer just received a message from an object with non-existing objectId[" << msg->objectId << "]\n";
    return false;
}

void GameInstanceServer::connectLocallyTo(MessagePeer* buddy, bool recursive /*= true*/)
{
    // we have got a new client! Create a SpaceShip just for him
    GameMessagePeer::connectLocallyTo(buddy, recursive);

    SpaceShipServer::pointer hisShip{
        new SpaceShipServer(osg::Vec3f(), osg::Quat(0, osg::Vec3f(1, 0, 0)), RemotePeersManager::getManager()->getPeersId(buddy), this, m_physicsEngine) };

    //GameMessage::pointer constructItMsg = m_asteroidField->creationMessage();
    //buddy->send(constructItMsg);
    GameMessage::pointer constructItMsg;
    for (std::pair<MessagePeer*, SpaceShipServer::pointer> aShip : m_peerSpaceShips)
    {
        constructItMsg = aShip.second->creationMessage();
        buddy->send(constructItMsg);
    }
    broadcastLocally(hisShip->creationMessage());
    m_peerSpaceShips.insert(std::make_pair(buddy, hisShip));

    GameMessage::pointer constructGameInfoMsg = m_gameInfo->creationMessage();
    buddy->send(constructGameInfoMsg);

    if (m_peerSpaceShips.size() >= MINPLAYERS && m_waitingForPlayers)
    {
        m_waitingForPlayers = false;
        newRound();
    }
}

void GameInstanceServer::newRound()
{
    std::random_device randDevice;
    //float range = m_asteroidField->getCubeSideLength();
    float range = 16.0; // todo: new range calculation?
    float maxRand = randDevice.max();

    osg::Vec3f startingPoint = osg::Vec3f(
        range*randDevice() / maxRand,
        range*randDevice() / maxRand,
        range*randDevice() / maxRand);
    osg::Vec3f finishArea = osg::Vec3f(
        range*randDevice() / maxRand,
        range*randDevice() / maxRand,
        range*randDevice() / maxRand);
    m_gameInfo->setObjective(startingPoint, finishArea, 1);

    GameMessage::pointer msg = m_gameInfo->objectiveMessage();
    btTransform t;
    for (std::map<MessagePeer*, SpaceShipServer::pointer>::iterator peerSpaceShip = m_peerSpaceShips.begin(); peerSpaceShip != m_peerSpaceShips.end(); ++peerSpaceShip)
    {
        //set ship positions to starting point
        osg::Vec3f v1 = osg::Vec3f(0, 0, 1), v2 = startingPoint - finishArea;
        osg::Vec3f a = v1 ^ v2;
        float w = sqrt(v1.length2() * v2.length2()) + v1*v2;
        btQuaternion q = btQuaternion(a.x(), a.y(), a.z(), w).normalize();
        t.setRotation(q);
        t.setOrigin(btVector3(startingPoint.x(), startingPoint.y(), startingPoint.z()));

        unsigned int physId = peerSpaceShip->second->getPhysicsId();

        m_physicsEngine->setShipTransformation(physId, t);

        //inform clients about new objective
        MessagePeer* buddy = peerSpaceShip->first;
        buddy->send(msg);

    }
}

void GameInstanceServer::disconnectLocallyFrom(MessagePeer* buddy, bool recursive /*= true*/)
{

    GameMessagePeer::disconnectLocallyFrom(buddy, recursive);

    SpaceShipServer::pointer shipToRemove = m_peerSpaceShips.at(buddy);
    NetRemoveGameObjectMessage::pointer removeMessage{ new NetRemoveGameObjectMessage };
    removeMessage->objectId = shipToRemove->getObjectId();
    broadcastLocally(removeMessage);

    m_peerSpaceShips.erase(buddy);

    if (m_peerSpaceShips.size() < MINPLAYERS)
    {
        m_waitingForPlayers = true;
    }

    std::vector <ChunkCoordinates> chunksToRemove;
    for (auto& chunk : m_universe)
    {
        std::deque<MessagePeer*> &observers = chunk.second.m_observers;
        auto endIter = observers.end();
        auto peerData = std::find(observers.begin(), endIter, buddy);
        if (peerData != endIter)
        {
            observers.erase(peerData);
            if (observers.empty())
                chunksToRemove.push_back(chunk.first);
        }
    }
    for (ChunkCoordinates const& coord : chunksToRemove)
        m_universe.erase(coord);
}

void GameInstanceServer::physicsTick(float timeInterval)
{
    m_physicsEngine->physicsTick(timeInterval);
    checkForEndround();
}

void GameInstanceServer::checkForEndround()
{
    bool someShipEnteredFinishArea = false;
    for (std::map<MessagePeer*, SpaceShipServer::pointer>::iterator peerSpaceShip = m_peerSpaceShips.begin(); peerSpaceShip != m_peerSpaceShips.end(); ++peerSpaceShip)
    {
        unsigned int physId = peerSpaceShip->second->getPhysicsId();
        osg::Vec3f pos = m_physicsEngine->getShipPosition(physId);
        if ( m_gameInfo->shipInFinishArea(pos) )
        {
            someShipEnteredFinishArea = true;
            break;
        }
    }
    if (someShipEnteredFinishArea)
    {
        //todo. update the players scores
        newRound();
    }
}

GameInstanceServer::ChunkCoordinates GameInstanceServer::positionToChunk(const osg::Vec3f& pos)
{
    return ChunkCoordinates(std::floor(pos.x() / 16.0),
        std::floor(pos.y() / 16.0),
        std::floor(pos.z() / 16.0));
}

bool GameInstanceServer::takeMessage(const NetMessage::const_pointer& msg, MessagePeer* peer)
{
    if (msg->gettype() == NetRequestChunkDataMessage::type)
    {
        NetRequestChunkDataMessage::const_pointer realMsg = msg->as<NetRequestChunkDataMessage>();
        osg::Vec3i chunkCoord = realMsg->coord;
        // A client has requested data about the chunk.
        // First look if we have it in our dictionary
        if (m_universe.count(chunkCoord) == 0)
        {
            // The chunk doesn't exist yet, generate it
            ServerChunkData newChunk;
            newChunk.m_asteroidField = std::make_shared<AsteroidFieldChunkServer>(100, 16, 0, chunkCoord, this, m_physicsEngine.get());
            m_universe.insert(std::make_pair(chunkCoord, newChunk));
        }

        ServerChunkData& myChunk = m_universe[chunkCoord];
        NetMessage::pointer reply = myChunk.m_asteroidField->creationMessage();
        myChunk.m_observers.push_back(peer);

        peer->send(reply, this);
        return true;
    }
    else if (msg->gettype() == NetStopChunkTrackingMessage::type)
    {
        NetRequestChunkDataMessage::const_pointer realMsg = msg->as<NetRequestChunkDataMessage>();
        osg::Vec3i chunkCoord = realMsg->coord;

        if (m_universe.count(chunkCoord) == 0)
            return false;
        ServerChunkData& myChunk = m_universe[chunkCoord];

        auto erasePosition = std::find(myChunk.m_observers.cbegin(), myChunk.m_observers.cend(), peer);
        if (erasePosition == myChunk.m_observers.cend())
            return false;

        myChunk.m_observers.erase(erasePosition);
        if (myChunk.m_observers.empty())
        {
            m_universe.erase(chunkCoord);
        }
        return true;
    }
    return GameMessagePeer::takeMessage(msg, peer);
}

osg::Vec3f GameInstanceServer::chunkToPosition(const osg::Vec3i& pos)
{
    return osg::Vec3f(pos.x() * 16.0, pos.y()*16.0, pos.z()*16.0);
}

<|endoftext|>


<commit_before>// ---------------------------------------------------------------------
//
// Copyright (C) 2015 by the deal.II authors
//
// This file is part of the deal.II library.
//
// The deal.II library is free software; you can use it, redistribute
// it, and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
// The full text of the license can be found in the file LICENSE at
// the top level of the deal.II distribution.
//
// ---------------------------------------------------------------------

// Test that it is possible to create a block diagonal linear operator
// from other linear operators involving Trilinos matrices.

#include "../tests.h"

#include <deal.II/lac/linear_operator.h>
#include <deal.II/lac/block_linear_operator.h>
#include <deal.II/lac/trilinos_block_sparse_matrix.h>
#include <deal.II/lac/trilinos_sparse_matrix.h>
#include <deal.II/lac/trilinos_vector.h>
#include <deal.II/lac/trilinos_block_vector.h>

using namespace dealii;

int main(int argc, char *argv[])
{
  Utilities::MPI::MPI_InitFinalize mpi_initialization (argc, argv, 1);

  initlog();
  deallog << std::setprecision(10);

  TrilinosWrappers::SparseMatrix a;

  auto op_a  = linear_operator<TrilinosWrappers::MPI::Vector>(a);
  auto op_a2  = linear_operator<TrilinosWrappers::Vector>(a);

  TrilinosWrappers::BlockSparseMatrix b;

  auto op_b = linear_operator<TrilinosWrappers::MPI::BlockVector>(b);
  auto op_b3 = linear_operator<TrilinosWrappers::BlockVector>(b);

  auto op_c = block_diagonal_operator<2, TrilinosWrappers::MPI::BlockVector >({{ op_a, op_a}});
  auto op_c2 = block_diagonal_operator<2, TrilinosWrappers::BlockVector >({{ op_a2, op_a2}});

  deallog << "OK" << std::endl;

  return 0;
}
<commit_msg>Work around a bug in gcc 4.6.<commit_after>// ---------------------------------------------------------------------
//
// Copyright (C) 2015 by the deal.II authors
//
// This file is part of the deal.II library.
//
// The deal.II library is free software; you can use it, redistribute
// it, and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
// The full text of the license can be found in the file LICENSE at
// the top level of the deal.II distribution.
//
// ---------------------------------------------------------------------

// Test that it is possible to create a block diagonal linear operator
// from other linear operators involving Trilinos matrices.

#include "../tests.h"

#include <deal.II/lac/linear_operator.h>
#include <deal.II/lac/block_linear_operator.h>
#include <deal.II/lac/trilinos_block_sparse_matrix.h>
#include <deal.II/lac/trilinos_sparse_matrix.h>
#include <deal.II/lac/trilinos_vector.h>
#include <deal.II/lac/trilinos_block_vector.h>

using namespace dealii;

int main(int argc, char *argv[])
{
  Utilities::MPI::MPI_InitFinalize mpi_initialization (argc, argv, 1);

  initlog();
  deallog << std::setprecision(10);

  TrilinosWrappers::SparseMatrix a;

  auto op_a  = linear_operator<TrilinosWrappers::MPI::Vector>(a);
  auto op_a2  = linear_operator<TrilinosWrappers::Vector>(a);

  TrilinosWrappers::BlockSparseMatrix b;

  auto op_b = linear_operator<TrilinosWrappers::MPI::BlockVector>(b);
  auto op_b3 = linear_operator<TrilinosWrappers::BlockVector>(b);

  typedef LinearOperator<TrilinosWrappers::MPI::Vector,TrilinosWrappers::MPI::Vector> Op_MPI;
  typedef LinearOperator<TrilinosWrappers::Vector,TrilinosWrappers::Vector> Op;

  auto op_c = block_diagonal_operator<2, TrilinosWrappers::MPI::BlockVector >(std::array<Op_MPI,2> ({{ op_a, op_a}}));
  auto op_c2 = block_diagonal_operator<2, TrilinosWrappers::BlockVector >(std::array<Op,2> ({{ op_a2, op_a2}}));

  deallog << "OK" << std::endl;

  return 0;
}
<|endoftext|>


<commit_before>#pragma once
//=====================================================================//
/*!	@file
	@brief	サークル・クラス @n
			・XY プロッタ(CNC)用の円周位置を生成するクラス @n
			・XY 座標は、一般的数学的座標系を使う。 @n
			・入出力は整数で行い、桁落ちなどの対策を行う。
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2018 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/glfw_app/blob/master/LICENSE
*/
//=====================================================================//
#include "common/vtx.hpp"

namespace imath {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief	円クラス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	class circle {

		static inline float sqrtf_(float x)
		{
			__asm __volatile(
				"fsqrt %0, %0\n" \
				: "+r"(x) \
			);
			return x;
		}

		vtx::ipos	start_;
		vtx::ipos	center_;
		vtx::ipos	term_;

		vtx::ipos	pos_;
		vtx::ipos	fin_;
		int32_t		rad_;
		int32_t		rad_sqr_;
		int32_t		oct_;

		bool		cw_;

		static int32_t octant_(const vtx::ipos& p) noexcept
		{
			uint32_t n = 0;
			if(std::abs(p.x) > std::abs(p.y)) n |= 0b001;
			if(p.x < 0) n |= 0b100;
			if(p.y < 0) n |= 0b010;
			static const int8_t map[8] = {
				0, 1, 3, 2, 7, 6, 4, 5
			};
			return map[n];
		}

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief	コンストラクタ
		 */
		//-----------------------------------------------------------------//
		circle() noexcept :  start_(0), center_(0), term_(0),
			pos_(0), fin_(0), rad_(0), rad_sqr_(0), oct_(0), cw_(true)
		{ }

		//-----------------------------------------------------------------//
		/*!
			@brief	角度に対する座標
			@param[in]	an	角度（０～１．０）@n
							※０：３時、０．２５：６時、０．５：９時、０．７５：１２時
			@param[in]	rad	半径
		 */
		//-----------------------------------------------------------------//
		static vtx::ipos angle_to_position(float an, int32_t rad) noexcept
		{
			vtx::ipos pos;
			pos.x = cosf(an * vtx::radian_f_) * static_cast<float>(rad);
			pos.y = sinf(an * vtx::radian_f_) * static_cast<float>(rad);
			return pos;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	機能テスト用
		 */
		//-----------------------------------------------------------------//
		void func_test() noexcept
		{
			{
				float an = 0.0f;
				for(int32_t i = 0; i < 20; ++i) {
					auto pos = angle_to_position(an, 10 * 2);
					auto len = pos.len();
					++len;
					len /= 2;
					utils::format("%5.4f %d\n") % an % len;
					an += 0.05f;
				}
			}

			{
				float an = 1.0f / 4.0f;
				an -= 1.0f / 16.0f;
				for(uint32_t i = 0; i < 8; ++i) {
					auto pos = angle_to_position(an, 100);
					auto n = octant_(pos);
					utils::format("%d\n") % n;
					an -= 1.0f / 8.0f;
				}
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	開始、終点を設定（１８０度以内である事）@n
					※円にする場合「開始」と「終点」を逆にしてもう一度呼ぶ
			@param[in]	sta	開始位置
			@param[in]	cen	中心位置
			@param[in]	fin	終端位置
			@param[in]	cw	反時計方向なら「false」
			@return 不整合なら「false」
		 */
		//-----------------------------------------------------------------//
		bool start(const vtx::ipos& sta, const vtx::ipos& cen, const vtx::ipos& fin, bool cw = true) noexcept
		{
			vtx::ipos d0 = sta - cen;
			vtx::ipos d1 = fin - cen;
			d0 *= 2;
			d1 *= 2;
			int32_t len0 = d0.len();
			++len0;
			len0 /= 2;
			int32_t len1 = d1.len();
			++len1;
			len1 /= 2;
			if(len0 != len1) {
				return false;
			}
			start_  = sta;
			center_ = cen;
			term_   = fin;
			cw_ = cw;
			oct_ = octant_(d1);

			rad_ = len0 * 2;
			rad_sqr_ = rad_ * rad_;
			pos_.x = d0.x;
			pos_.y = d0.y;
			fin_.x = d1.x;
			fin_.y = d1.y;

			return true;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	ステップ
			@return 終端なら「true」
		 */
		//-----------------------------------------------------------------//
		bool step() noexcept
		{
			bool limit = false;
			auto oct = octant_(pos_);
			switch(oct) {
			case 0:
			case 7:
				if(cw_) pos_.x += 2;
				else pos_.x -= 2;
				pos_.y = sqrtf_(rad_sqr_ - pos_.x * pos_.x);
				break;
			case 1:
			case 2:
				if(cw_) pos_.y -= 2;
				else pos_.y += 2;
				pos_.x = sqrtf_(rad_sqr_ - pos_.y * pos_.y);
				break;
			case 3:
			case 4:
				if(cw_) pos_.x -= 2;
				else pos_.x += 2;
				pos_.y = -sqrtf_(rad_sqr_ - pos_.x * pos_.x);
				break;
			case 5:
			case 6:
				if(cw_) pos_.y += 2;
				else pos_.y -= 2;
				pos_.x = -sqrtf_(rad_sqr_ - pos_.y * pos_.y);
				break;
			}
			if(oct != oct_) return false;

			switch(oct_) {
			case 0:
			case 1:
				if(cw_) {
					if(pos_.x >= fin_.x && pos_.y <= fin_.y) limit = true;
				} else {
					if(pos_.x <= fin_.x && pos_.y >= fin_.y) limit = true;
				}
				break;
			case 2:
			case 3:
				if(cw_) {
					if(pos_.x <= fin_.x && pos_.y <= fin_.y) limit = true;
				} else {
					if(pos_.x >= fin_.x && pos_.y >= fin_.y) limit = true;
				}
				break;
			case 4:
			case 5:
				if(cw_) {
					if(pos_.x <= fin_.x && pos_.y <= fin_.y) limit = true;
				} else {
					if(pos_.x >= fin_.x && pos_.y >= fin_.y) limit = true;
				}
				break;
			case 6:
			case 7:
				if(cw_) {
					if(pos_.x >= fin_.x && pos_.y >= fin_.y) limit = true;
				} else {
					if(pos_.x <= fin_.x && pos_.y <= fin_.y) limit = true;
				}
				break;
			}

			return limit;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	生成された位置を取得
			@return 生成された位置
		 */
		//-----------------------------------------------------------------//
		vtx::ipos get_position() const noexcept
		{
			vtx::ipos p;
			p.x = (pos_.x + 1) / 2 + center_.x;
			p.y = (pos_.y + 1) / 2 + center_.y;
			return p;
		}
	};
}
<commit_msg>update: sqrt call<commit_after>#pragma once
//=====================================================================//
/*!	@file
	@brief	サークル・クラス @n
			・XY プロッタ(CNC)用の円周位置を生成するクラス @n
			・XY 座標は、一般的数学的座標系を使う。 @n
			・入出力は整数で行い、桁落ちなどの対策を行う。
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2018 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/glfw_app/blob/master/LICENSE
*/
//=====================================================================//
#include "common/vtx.hpp"

namespace imath {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief	円クラス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	class circle {

		vtx::ipos	start_;
		vtx::ipos	center_;
		vtx::ipos	term_;

		vtx::ipos	pos_;
		vtx::ipos	fin_;
		int32_t		rad_;
		int32_t		rad_sqr_;
		int32_t		oct_;

		bool		cw_;

		static int32_t octant_(const vtx::ipos& p) noexcept
		{
			uint32_t n = 0;
			if(std::abs(p.x) > std::abs(p.y)) n |= 0b001;
			if(p.x < 0) n |= 0b100;
			if(p.y < 0) n |= 0b010;
			static const int8_t map[8] = {
				0, 1, 3, 2, 7, 6, 4, 5
			};
			return map[n];
		}

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief	コンストラクタ
		 */
		//-----------------------------------------------------------------//
		circle() noexcept :  start_(0), center_(0), term_(0),
			pos_(0), fin_(0), rad_(0), rad_sqr_(0), oct_(0), cw_(true)
		{ }

		//-----------------------------------------------------------------//
		/*!
			@brief	角度に対する座標
			@param[in]	an	角度（０～１．０）@n
							※０：３時、０．２５：６時、０．５：９時、０．７５：１２時
			@param[in]	rad	半径
		 */
		//-----------------------------------------------------------------//
		static vtx::ipos angle_to_position(float an, int32_t rad) noexcept
		{
			vtx::ipos pos;
			pos.x = cosf(an * vtx::radian_f_) * static_cast<float>(rad);
			pos.y = sinf(an * vtx::radian_f_) * static_cast<float>(rad);
			return pos;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	機能テスト用
		 */
		//-----------------------------------------------------------------//
		void func_test() noexcept
		{
			{
				float an = 0.0f;
				for(int32_t i = 0; i < 20; ++i) {
					auto pos = angle_to_position(an, 10 * 2);
					auto len = pos.len();
					++len;
					len /= 2;
					utils::format("%5.4f %d\n") % an % len;
					an += 0.05f;
				}
			}

			{
				float an = 1.0f / 4.0f;
				an -= 1.0f / 16.0f;
				for(uint32_t i = 0; i < 8; ++i) {
					auto pos = angle_to_position(an, 100);
					auto n = octant_(pos);
					utils::format("%d\n") % n;
					an -= 1.0f / 8.0f;
				}
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	開始、終点を設定（１８０度以内である事）@n
					※円にする場合「開始」と「終点」を逆にしてもう一度呼ぶ
			@param[in]	sta	開始位置
			@param[in]	cen	中心位置
			@param[in]	fin	終端位置
			@param[in]	cw	反時計方向なら「false」
			@return 不整合なら「false」
		 */
		//-----------------------------------------------------------------//
		bool start(const vtx::ipos& sta, const vtx::ipos& cen, const vtx::ipos& fin, bool cw = true) noexcept
		{
			vtx::ipos d0 = sta - cen;
			vtx::ipos d1 = fin - cen;
			d0 *= 2;
			d1 *= 2;
			int32_t len0 = d0.len();
			++len0;
			len0 /= 2;
			int32_t len1 = d1.len();
			++len1;
			len1 /= 2;
			if(len0 != len1) {
				return false;
			}
			start_  = sta;
			center_ = cen;
			term_   = fin;
			cw_ = cw;
			oct_ = octant_(d1);

			rad_ = len0 * 2;
			rad_sqr_ = rad_ * rad_;
			pos_.x = d0.x;
			pos_.y = d0.y;
			fin_.x = d1.x;
			fin_.y = d1.y;

			return true;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	ステップ
			@return 終端なら「true」
		 */
		//-----------------------------------------------------------------//
		bool step() noexcept
		{
			bool limit = false;
			auto oct = octant_(pos_);
			switch(oct) {
			case 0:
			case 7:
				if(cw_) pos_.x += 2;
				else pos_.x -= 2;
				pos_.y = vtx::fsqrt(rad_sqr_ - pos_.x * pos_.x);
				break;
			case 1:
			case 2:
				if(cw_) pos_.y -= 2;
				else pos_.y += 2;
				pos_.x = vtx::fsqrt(rad_sqr_ - pos_.y * pos_.y);
				break;
			case 3:
			case 4:
				if(cw_) pos_.x -= 2;
				else pos_.x += 2;
				pos_.y = -vtx::fsqrt(rad_sqr_ - pos_.x * pos_.x);
				break;
			case 5:
			case 6:
				if(cw_) pos_.y += 2;
				else pos_.y -= 2;
				pos_.x = -vtx::fsqrt(rad_sqr_ - pos_.y * pos_.y);
				break;
			}
			if(oct != oct_) return false;

			switch(oct_) {
			case 0:
			case 1:
				if(cw_) {
					if(pos_.x >= fin_.x && pos_.y <= fin_.y) limit = true;
				} else {
					if(pos_.x <= fin_.x && pos_.y >= fin_.y) limit = true;
				}
				break;
			case 2:
			case 3:
				if(cw_) {
					if(pos_.x <= fin_.x && pos_.y <= fin_.y) limit = true;
				} else {
					if(pos_.x >= fin_.x && pos_.y >= fin_.y) limit = true;
				}
				break;
			case 4:
			case 5:
				if(cw_) {
					if(pos_.x <= fin_.x && pos_.y <= fin_.y) limit = true;
				} else {
					if(pos_.x >= fin_.x && pos_.y >= fin_.y) limit = true;
				}
				break;
			case 6:
			case 7:
				if(cw_) {
					if(pos_.x >= fin_.x && pos_.y >= fin_.y) limit = true;
				} else {
					if(pos_.x <= fin_.x && pos_.y <= fin_.y) limit = true;
				}
				break;
			}

			return limit;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	生成された位置を取得
			@return 生成された位置
		 */
		//-----------------------------------------------------------------//
		vtx::ipos get_position() const noexcept
		{
			vtx::ipos p;
			p.x = (pos_.x + 1) / 2 + center_.x;
			p.y = (pos_.y + 1) / 2 + center_.y;
			return p;
		}
	};
}
<|endoftext|>