/** Test functionality of the sceneCollisionManager */
bool sceneCollisionManager(void)
{
	IrrlichtDevice * device = irr::createDevice(video::EDT_NULL, dimension2d<u32>(160, 120));
	assert(device);
	if(!device)
		return false;

	ISceneManager * smgr = device->getSceneManager();
	ISceneCollisionManager * collMgr = smgr->getSceneCollisionManager();

	bool result = testGetCollisionResultPosition(device, smgr, collMgr);

	smgr->clear();

	result &= testGetSceneNodeFromScreenCoordinatesBB(device, smgr, collMgr);

	result &= getScaledPickedNodeBB(device, smgr, collMgr);

	result &= getCollisionPoint_ignoreTriangleVertices(device, smgr, collMgr);

	result &= checkBBoxIntersection(device, smgr);

	result &= compareGetSceneNodeFromRayBBWithBBIntersectsWithLine(device, smgr, collMgr);

	device->closeDevice();
	device->run();
	device->drop();
	return result;
}
Exemple #2
0
//получение объекта сцены, который выбра пользователем
void CNrpMainScene::GetNodeAndIntersectionFromCursor_( scene::ISceneNode*& node, core::vector3df& point, bool &doubleClick )
{
	ISceneManager* smgr = _nrpEngine.GetSceneManager();

	//координаты курсора на экране
	core::position2di pos = _nrpEngine.GetDevice()->getCursorControl()->getPosition();
	//получаем луч для расчетов
	core::line3df line = smgr->getSceneCollisionManager()->getRayFromScreenCoordinates( pos, smgr->getActiveCamera() );		
	//здесь будет выбранный треугольник
	core::triangle3df tri;
	//получаем выбранный объект
	node = smgr->getSceneCollisionManager()->getSceneNodeAndCollisionPointFromRay( line, point, tri );
	//устанавливаем флаг двойного нажатия мышкой
	doubleClick = ( selectedNode_ == node ) && ( GetTickCount() - lastTimeNodeSelect_ < 200 );
	lastTimeNodeSelect_ = GetTickCount();
}
// selectObject
// detect list objs at rect
void CDocument::selectObject( int x, int y, int w, int h, bool isControlHold )
{
	IView *pView = getIView();
	ISceneManager *smgr = pView->getSceneMgr();	
	
	ICameraSceneNode *camera = smgr->getActiveCamera();

	// if no camera
	if (  camera == NULL )
		return;

	const SViewFrustum* viewFrustum = camera->getViewFrustum();
	ISceneCollisionManager *collMan = smgr->getSceneCollisionManager();

	int screenX = -1, screenY = -1;
		
	ArrayZoneIter iZone = m_zones.begin(), iEnd = m_zones.end();
	while ( iZone != iEnd )
	{
		ArrayGameObject* listObj = (*iZone)->getChilds();
		ArrayGameObjectIter iObj = listObj->begin(), objEnd = listObj->end();
		ISceneNode *pNode = NULL;

		while ( iObj != objEnd )
		{
			CGameObject *pGameObj = (CGameObject*)(*iObj);
			
			pNode = pGameObj->getSceneNode();
			
			if ( pNode != NULL && pGameObj->isVisible() )
			{
				core::vector3df center = pGameObj->getPosition();

				// check object is in frustum
				if ( viewFrustum->getBoundingBox().isPointInside( center ) )
				{					
					if ( pView->getScreenCoordinatesFrom3DPosition( center, &screenX, &screenY ) )
					{
						if ( x <= screenX && screenX <= x + w && y <= screenY && screenY <= y + h )
						{
							
							if ( isControlHold == false || pGameObj->getObjectState() == CGameObject::Normal )
								m_selectObjects.push_back( pGameObj );							

						}	// inselect
					}	// getScreenCoordinatesFrom3DPosition			
				} // frustum
			}

			iObj++;
		}

		iZone++;
	}

}
Exemple #4
0
int main()
{
	Input input;
	IrrlichtDevice *device = createDevice(video::EDT_DIRECT3D9, dimension2d<u32>(800, 600), 16, false, true, false, &input);
	device->setWindowCaption(L"Seas of Gold");
	IVideoDriver* driver = device->getVideoDriver();
	ISceneManager* smgr = device->getSceneManager();
	IGUIEnvironment* guienv = device->getGUIEnvironment();
	E_DRIVER_TYPE driverType = driverChoiceConsole();
	EffectHandler *effect = new EffectHandler(device, driver->getScreenSize(), false, true);
	E_FILTER_TYPE filterType = (E_FILTER_TYPE)core::clamp<u32>((u32)3 - '1', 0, 4);
	MapID currentMap;
	int skyR = 30, skyG = 30, skyB = 70;
	int timer = 0;
	SColor sky = SColor(255, skyR, skyG, skyB);
	float plPos_x = 0.0f, plPos_y = 0.0f, plPos_z = 0.0f;
	bool updateCam = true;
	bool menu1 = false;
	int state = Main;
	int frameCount = 0;
	LoadMap loadMap;
	Player player;
	Interface playerInterface(driver);
	ITriangleSelector* selector = 0;
	ISceneNodeAnimator* anim = 0;
	Vendor southVendor;
	Vendor eastVendor;
	Vendor northVendor;
	//InitializeVendors(northVendor, southVendor, eastVendor, itemD);

	//ItemDatabase* itemD = new ItemDatabase;
	ItemDatabase itemD;
	itemD.Initialize();

	//initialize player's inventory
	player.AddGold(1000);
	player.getInventory()->addItem(itemD.getItem(bronzeOre), 50);
	player.getInventory()->addItem(itemD.getItem(ironOre), 50);
	player.getInventory()->addItem(itemD.getItem(goldOre), 50);

	//initialize south vendor's inventory
	southVendor.getInventory()->addItem(itemD.getItem(bronzeOre), 100);
	southVendor.getInventory()->addItem(itemD.getItem(coalOre), 100);
	southVendor.getInventory()->addItem(itemD.getItem(supplies), 1000);

	//initialize north vendor's inventory
	northVendor.getInventory()->addItem(itemD.getItem(obsidianOre), 50);
	northVendor.getInventory()->addItem(itemD.getItem(supplies), 1000);

	//initialize south vendor's inventory
	eastVendor.getInventory()->addItem(itemD.getItem(goldOre), 100);
	eastVendor.getInventory()->addItem(itemD.getItem(ironOre), 100);
	eastVendor.getInventory()->addItem(itemD.getItem(supplies), 1000);

	//Item item(0, "bronzeOre", "Sprites/ore_Bronze.png");
	//Item item2 = item;
	//Item* item2 = itemD.getItem(3);
	//inventory.addItem(&item, 2);
	//inventory.addItem(&item, 2);
	//inventory.addItem(item2, 2);

	//int test = 0;

	// Load the map scene
	//loadMap.Load(smgr, device, Map_Africa);
	//loadMap.Load(smgr, device, Map_India);
	//loadMap.Load(smgr, device, selector, plyrNode, anim, Map_England);

	IAnimatedMeshSceneNode* plyrNode = player.loadPlayerNode(device, smgr);
	//plyrNode->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(plyrNode->isDebugDataVisible() ^ scene::EDS_BBOX));

	ICameraSceneNode* camera = smgr->addCameraSceneNode(0, plyrNode->getPosition() + vector3df(0, 2, 2), vector3df(0, 0, 100));

	loadMap.Load(smgr, device, selector, plyrNode, anim, driver, Map_Africa);
	currentMap = Map_Africa;
	//loadMap.setCollisions(smgr, selector, plyrNode, anim);

	if (loadMap.CollNode)
	{
		selector = smgr->createOctreeTriangleSelector(loadMap.CollNode->getMesh(), loadMap.CollNode, 32);
		for (int i = 0; i < loadMap.CollNode->getMaterialCount(); i++)
		{
			loadMap.CollNode->getMaterial(i).NormalizeNormals = true;
		}
		loadMap.CollNode->setTriangleSelector(selector);
	}

	if (selector)
	{
		anim = smgr->createCollisionResponseAnimator(selector, plyrNode, vector3df(0.6f, 0.75f, 0.4f), core::vector3df(0.0f, -0.05f, 0.0f),
			core::vector3df(0.0f, -0.725f, 0.0f));

		plyrNode->addAnimator(anim);
	}

	ISceneCollisionManager* collMan = smgr->getSceneCollisionManager();

	////////////// The Sun ////////////
	ILightSceneNode *sun_node;
	SLight sun_data;
	ISceneNode *sun_billboard;
	float sun_angle = 0;
	video::SColorf Diffuse_Night = video::SColorf(0.0f, 0.0f, 0.0f, 1.0f);
	video::SColorf Diffuse_Day = video::SColorf(1.0f, 1.0f, 1.0f, 1.0f);

	sun_node = smgr->addLightSceneNode();
	sun_data.Direction = vector3df(0, 0, 0);
	sun_data.Type = video::ELT_DIRECTIONAL;
	sun_data.AmbientColor = video::SColorf(0.1f, 0.1f, 0.1f, 1);
	sun_data.SpecularColor = video::SColorf(0, 0, 0, 0);
	sun_data.DiffuseColor = Diffuse_Day;
	sun_data.CastShadows = true;
	sun_node->setLightData(sun_data);
	sun_node->setPosition(vector3df(0, 0, 0));
	sun_node->setRotation(vector3df(0, 0, 0));

	sun_billboard = smgr->addBillboardSceneNode(sun_node, core::dimension2d<f32>(60, 60));
	if (sun_billboard)
	{
		sun_billboard->setPosition(vector3df(0, 0, -100));
		sun_billboard->setMaterialFlag(video::EMF_LIGHTING, false);
		sun_billboard->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false);
		sun_billboard->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR);
		sun_billboard->setMaterialTexture(0, driver->getTexture("Assets/particlewhite.bmp"));
	}
	/////////// End ////////////

	//------- candleLight -----//
	ILightSceneNode *candleLight = smgr->addLightSceneNode();
	SLight candleLight_data;

	candleLight_data.Type = video::ELT_POINT;
	candleLight_data.DiffuseColor = SColorf(1.0f, 0.546f, 0.016f, 1.0f);
	candleLight_data.SpecularColor = video::SColorf(0, 0, 0, 0);
	candleLight->setPosition(vector3df(2.43467f, 1.55795f, -3.94657));
	candleLight_data.Radius = 1.5f;
	candleLight->setLightData(candleLight_data);
	//------- end -----//

	//// Make the player
	//player.AddGold(1000);
	//player.SetCurrentPort(eMapDest::South);
	//Item* itemCi = new Item("Iron Ore", 1);
	//player.getItems()->addItem(itemCi);
	//Item* itemCb = new Item("Bronze Ore", 1);
	//player.getItems()->addItem(itemCb);

	//Vendor vN;
	//Item* itemG = new Item("Gold Ore", 1000);
	//vN.getItems()->addItem(itemG);
	//Vendor vS;
	//Item* itemI = new Item("Iron Ore", 1000);
	//vS.getItems()->addItem(itemI);
	//Vendor vE;
	//Item* itemB = new Item("Bronze Ore", 1000);
	//vE.getItems()->addItem(itemB);
	//Vendor northVendor

	//delete &itemD;

	int test99 = 0;


	// Make the menus
	MainMenu mainMenu(device, driver);

	MapMenu mapMenu(device, driver);
	mapMenu.SetPlayer(&player);

	TradeMenu tradeMenu;
	tradeMenu.Initialize(device, driver, &player, &southVendor);
	//TradeMenu tradeMenu(device, driver);
	//tradeMenu.SetPlayer(&player);
	//tradeMenu.SetVendor(&vS);
	//
	CraftingMenu craftMenu(device, driver, &player, itemD);
	//craftMenu.SetPlayer(&player);

	//////////////////////////////////////////////////////////////////////////
	// Initialize timer to compute elapsed time between frames
	//////////////////////////////////////////////////////////////////////////
	__int64 cntsPerSec = 0;
	QueryPerformanceFrequency((LARGE_INTEGER*)&cntsPerSec);
	float secsPerCnt = 1.0f / (float)cntsPerSec;

	__int64 prevTimeStamp = 0;
	QueryPerformanceCounter((LARGE_INTEGER*)&prevTimeStamp);

	while (device->run())
	{
		//for scaling animation by time, not by frame
		__int64 currTimeStamp = 0;
		QueryPerformanceCounter((LARGE_INTEGER*)&currTimeStamp);
		float dt = (currTimeStamp - prevTimeStamp) * secsPerCnt;

		sun_node->setRotation(vector3df(sun_angle, 0.0f, 0.0f));
		sun_angle += dt;
		frameCount += 1;
		if ((sun_angle > 0 && sun_angle < 109) || (sun_angle>350))
		{
			timer++;
			if (timer > 10)
			{
				if (skyR < 100) skyR += 1;
				if (skyG < 100) skyG += 1;
				if (skyB < 140) skyB += 1;
				timer = 0;
			}
		}
		if (sun_angle > 170 && sun_angle < 330)
		{
			timer++;
			if (timer > 10)
			{
				if (skyR > 0) skyR -= 1;
				if (skyG > 0) skyG -= 1;
				if (skyB > 40) skyB -= 1;
				timer = 0;
			}
		}

		player.updatePlayer(plyrNode, dt, collMan, selector);
		playerInterface.update(plyrNode, loadMap, driver, device, input, updateCam, state);

		switch (state)
		{
		case Map:
		{
			int out = mapMenu.Update(&input, frameCount);

			switch (out)
			{
			case eMapDest::Exit:
			{
				state = None;
				break;
			}
			case eMapDest::East:
			{
				state = None;
				//Item* itemB = new Item("Bronze Ore", 1000);
				//vE.getItems()->addItem(itemB);
				tradeMenu.SetVendor(&eastVendor);
				loadMap.Load(smgr, device, selector, plyrNode, anim, driver, Map_India);
				currentMap = Map_India;
				if (loadMap.CollNode)
				{
					selector = smgr->createOctreeTriangleSelector(loadMap.CollNode->getMesh(), loadMap.CollNode, 32);

					for (int i = 0; i < loadMap.CollNode->getMaterialCount(); i++)
					{
						loadMap.CollNode->getMaterial(i).NormalizeNormals = true;
					}
					loadMap.CollNode->setTriangleSelector(selector);
				}

				if (selector)
				{
					anim = smgr->createCollisionResponseAnimator(selector, plyrNode, vector3df(0.6f, 0.75f, 0.4f), core::vector3df(0.0f, -0.05f, 0.0f),
						core::vector3df(0.0f, -0.725f, 0.0f));
					plyrNode->addAnimator(anim);
				}
				collMan = smgr->getSceneCollisionManager();
				break;
			}
			case eMapDest::North:
			{
				state = None;
				//Item *itemG = new Item("Gold Ore", 1000);
				//vN.getItems()->addItem(itemG);
				//tradeMenu.SetVendor(&vN);
				tradeMenu.SetVendor(&northVendor);
				loadMap.Load(smgr, device, selector, plyrNode, anim, driver, Map_England);
				currentMap = Map_England;
				if (loadMap.CollNode)
				{
					selector = smgr->createOctreeTriangleSelector(loadMap.CollNode->getMesh(), loadMap.CollNode, 32);

					for (int i = 0; i < loadMap.CollNode->getMaterialCount(); i++)
					{
						loadMap.CollNode->getMaterial(i).NormalizeNormals = true;
					}
					loadMap.CollNode->setTriangleSelector(selector);
				}

				if (selector)
				{
					anim = smgr->createCollisionResponseAnimator(selector, plyrNode, vector3df(0.6f, 0.75f, 0.4f), core::vector3df(0.0f, -0.05f, 0.0f),
						core::vector3df(0.0f, -0.725f, 0.0f));
					plyrNode->addAnimator(anim);
				}
				collMan = smgr->getSceneCollisionManager();
				break;
			}
			case eMapDest::South:
			{
				state = None;
				//Item *itemI = new Item("Iron Ore", 1000);
				//vS.getItems()->addItem(itemI);
				//tradeMenu.SetVendor(&vS);
				tradeMenu.SetVendor(&southVendor);
				loadMap.Load(smgr, device, selector, plyrNode, anim, driver, Map_Africa);
				currentMap = Map_Africa;
				if (loadMap.CollNode)
				{
					selector = smgr->createOctreeTriangleSelector(loadMap.CollNode->getMesh(), loadMap.CollNode, 32);

					for (int i = 0; i < loadMap.CollNode->getMaterialCount(); i++)
					{
						loadMap.CollNode->getMaterial(i).NormalizeNormals = true;
					}
					loadMap.CollNode->setTriangleSelector(selector);
				}

				if (selector)
				{
					anim = smgr->createCollisionResponseAnimator(selector, plyrNode, vector3df(0.6f, 0.75f, 0.4f), core::vector3df(0.0f, -0.05f, 0.0f),
						core::vector3df(0.0f, -0.725f, 0.0f));
					plyrNode->addAnimator(anim);
				}
				collMan = smgr->getSceneCollisionManager();
				break;
			}
			default:
				break;
			}

			break;
		}
		case Trade:
		{

			bool out = false;
			out = tradeMenu.Update(&input, frameCount, device, currentMap);
			if (out)
				state = None;
			break;
		}
		case Main:
		{
			int out = mainMenu.Update(&input, frameCount);

			switch (out)
			{
			case MSstart:
			{
				state = None;
				break;
			}
			case MSexit:
			{
				device->closeDevice();
				//return 0;
				break;
			}
			default:
				break;
			}

			break;
		}
		case Craft:
		{
			bool out = craftMenu.Update(&input, frameCount, device);
			if (out)
				state = None;
			break;
		}
		default:
			// Do nothing
			break;
		}

		if (updateCam) moveCameraControl(plyrNode, device, camera);

		////////////////////////////////////////////////////////

		if (sun_angle > 360) sun_angle = 0;
		if (sun_angle < 180) sun_data.DiffuseColor = Diffuse_Day; else sun_data.DiffuseColor = Diffuse_Night;
		sun_node->setLightData(sun_data);

		sky.setRed(skyR);
		sky.setGreen(skyG);
		sky.setBlue(skyB);
		driver->beginScene(true, true, sky);

		smgr->drawAll();

		playerInterface.render(driver, state);

		// Draw the menu
		switch (state)
		{
		case Map:
		{
			mapMenu.Draw(driver, device);
			break;
		}
		case Trade:
		{
			tradeMenu.Render(driver, device);
			break;
		}
		case Main:
		{
			mainMenu.Draw(driver);
			break;
		}
		case Craft:
		{
			craftMenu.Draw(driver);
			break;
		}
		default:
			// Do nothing
			break;
		}

		driver->endScene();
		
		// Update the prev time stamp to current
		prevTimeStamp = currTimeStamp;

	}

	device->drop();

	return 0;
}
void CDR::update(NBEditor* editor, bool drag, rect<s32> offset)
{
	if (!editor->state->project) {
		return;
	}

	if (!editor->state->settings->getBool("always_show_position_handle") &&
			(editor->state->keys[KEY_LSHIFT] == EKS_UP) ==
			(type == CDR_XY || type == CDR_XZ || type == CDR_ZY)) {
		return;
	}

	Node* node = editor->state->project->GetCurrentNode();

	if (!node) {
		return;
	}

	NodeBox *box = node->GetCurrentNodeBox();

	if (!box) {
		return;
	}

	ISceneManager * smgr = editor->state->device->getSceneManager();

	if (drag) {
		// get mouse position
		position2di target = editor->state->mouse_position;
		target -= offset.UpperLeftCorner;

		// Get the ray
		line3d<irr::f32> ray = smgr->getSceneCollisionManager()
				->getRayFromScreenCoordinates(target, smgr->getActiveCamera());

		// Contains the output values
		vector3df wpos = vector3df(0, 0, 0); // The collision position

		// Not used, but required for function
		#if IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8
			const ISceneNode* tmpNode;
		#else
			ISceneNode* tmpNode;
		#endif
		triangle3df tmpTri;

		// Execute ray
		smgr->getSceneCollisionManager()->getCollisionPoint(ray,
				editor->state->plane_tri, wpos, tmpTri, tmpNode);

		// Snapping
		wpos -= vector3df(node->position.X, node->position.Y, node->position.Z);
		if (window == VIEW_XZ)
			wpos.Z -= 0.1;

		if (editor->state->settings->getBool("snapping")) {
			wpos.X = floor((wpos.X + 0.5) * 16 + 0.5) / 16 - 0.5;
			wpos.Y = floor((wpos.Y + 0.5) * 16 + 0.5) / 16 - 0.5;
			wpos.Z = floor((wpos.Z + 0.5) * 16 + 0.5) / 16 - 0.5;
		}

		// Do node limiting
		if (editor->state->settings->getBool("limiting")) {
			// X Axis
			if (wpos.X < -0.5) {
				wpos.X = -0.5;
			} else if (wpos.X > 0.5) {
				wpos.X = 0.5;
			}

			// Y Axis
			if (wpos.Y < -0.5) {
				wpos.Y = -0.5;
			} else if (wpos.Y > 0.5) {
				wpos.Y = 0.5;
			}

			// Z Axis
			if (wpos.Z < -0.5) {
				wpos.Z = -0.5;
			} else if (wpos.Z > 0.5) {
				wpos.Z = 0.5;
			}
		}

		// Call required function
		if (type < CDR_XZ) {
			box->resizeNodeBoxFace(editor->state, type, wpos,
				editor->state->keys[KEY_LCONTROL] == EKS_DOWN);
		} else {
			box->moveNodeBox(editor->state, type, wpos);
		}
		node->remesh();

		editor->triggerCDRmoved();
	}

	vector3df pos = box->GetCenter();

	switch (type) {
	case CDR_X_P:
		pos.X = box->two.X;
		break;
	case CDR_X_N:
		pos.X = box->one.X;
		break;
	case CDR_Y_P:
		pos.Y = box->two.Y;
		break;
	case CDR_Y_N:
		pos.Y = box->one.Y;
		break;
	case CDR_Z_P:
		pos.Z = box->two.Z;
		break;
	case CDR_Z_N:
		pos.Z = box->one.Z;
		break;
	default:
		break;
	}

	pos.X += node->position.X;
	pos.Y += node->position.Y;
	pos.Z += node->position.Z;

	vector2d<irr::s32> cpos = smgr->getSceneCollisionManager()
			->getScreenCoordinatesFrom3DPosition(
				pos,
				smgr->getActiveCamera()
	#if !(IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8)
				, true
	#endif
			);

	position = cpos + offset.UpperLeftCorner;
	visible = true;
}
// selectObject
// detect list objs at mouse xy	
void CDocument::selectObject( int mouseX, int mouseY, bool isControlHold )
{	
	ISceneManager *smgr = getIView()->getSceneMgr();	
	
	ICameraSceneNode *camera = smgr->getActiveCamera();

	// if no camera
	if (  camera == NULL )
		return;

	ISceneCollisionManager *collMan = smgr->getSceneCollisionManager();

	// get select ray
	core::line3df selectRay = getIView()->getSelectRay();
	
	// check hit test
	core::vector3df intersection;
	core::triangle3df hitTriangle;

	// check select
	ISceneNode *selectedSceneNode = collMan->getSceneNodeAndCollisionPointFromRay
		(
			selectRay,
			intersection,
			hitTriangle
		);
	
	if ( selectedSceneNode )
	{
		CGameObject *pObj =	searchObject( selectedSceneNode->getID() );
		
		// try find parent
		while ( pObj == NULL )
		{
			selectedSceneNode = selectedSceneNode->getParent();
			if ( selectedSceneNode == NULL )
				break;
			pObj = searchObject( selectedSceneNode->getID() );
		}

		// add to select list
		if ( pObj && pObj->isVisible() )
		{
			if ( isControlHold == false || pObj->getObjectState() == CGameObject::Normal )
				m_selectObjects.push_back( pObj );
			else
			{
				pObj->setObjectState( CGameObject::Normal );
				ArrayGameObjectIter i = m_selectObjects.begin(), iEnd = m_selectObjects.end();
				while ( i != iEnd )
				{
					if ( (*i) == pObj )
					{
						m_selectObjects.erase( i );
						break;
					}
					i++;
				}
			}
		}

	}

}
int main(int argc, char** argv) {
	CustomEventReceiver receiver;
	IrrlichtDevice *device = createDevice( video::EDT_OPENGL, dimension2d<u32>(800, 600), 16, false, false, false, &receiver);
	if (!device) {
		return EXIT_FAILURE;
    }
	device->setWindowCaption(L"Solar System Simulator");
	IVideoDriver* driver = device->getVideoDriver();
	ISceneManager* sceneManager = device->getSceneManager();
	scene::ISceneCollisionManager* collisionManager= sceneManager->getSceneCollisionManager();
	IGUIEnvironment* guiEnv = device->getGUIEnvironment();
	guiEnv->addStaticText(L"Click on a planet to attach the camera to it", rect<s32>(10,10,260,22), false);

	sf::SoundBuffer buffer;
	if (buffer.loadFromFile(currentPath() + "/sounds/burning.aif")) {
		sf::Listener::setPosition(0, 0,0);

		sf::Sound sound;
		sound.setBuffer(buffer);
		sound.setPosition(0, 0, 0);
		sound.setLoop(true);
		sound.play();
	}

	const char* spaceTexturePath = ( currentPath() + "/textures/space.jpg" ).c_str();
	video::ITexture* space = driver->getTexture(spaceTexturePath);
	scene::ISceneNode* skybox = sceneManager->addSkyBoxSceneNode(space, space, space, space, space, space);

	sceneManager->addLightSceneNode(0, vector3df(0, 0, -50),  video::SColorf(1.0f, 1.0f, 1.0f), 50.0f, 1001);

	PlanetFactory planetFactory(sceneManager, driver);
	Planet sun = planetFactory.create(PlanetId::Sun);
	Planet earth = planetFactory.create(PlanetId::Earth);
	Planet pluto = planetFactory.create(PlanetId::Pluto);
	Planet jupiter = planetFactory.create(PlanetId::Jupiter);
	Planet uranus = planetFactory.create(PlanetId::Uranus);
	Planet neptune = planetFactory.create(PlanetId::Neptune);

	vector<Planet> planets = { sun, planetFactory.create(PlanetId::Mercury) };
	planets.push_back(planetFactory.create(PlanetId::Venus));
	planets.push_back(earth);
	planets.push_back(planetFactory.create(PlanetId::Mars));
	planets.push_back(jupiter);
	planets.push_back(planetFactory.create(PlanetId::Saturn));
	planets.push_back(uranus);
	planets.push_back(neptune);
	planets.push_back(pluto);

	ICameraSceneNode* camera = sceneManager->addCameraSceneNode(0, vector3df(0,0,40), vector3df(0,0,0));
	rect<s32> mainCameraViewPortRect(0, 0, 800, 600);

	ICameraSceneNode* topViewCamera = sceneManager->addCameraSceneNode(0, vector3df(0,50,0), vector3df(0,0,0));
	
	sceneManager->setAmbientLight(video::SColorf(255.0,255.0,255.0));

	ISceneNode* selectedNode = sun.node;
	while(device->run()) {

		if(receiver.GetMouseState().LeftButtonDown) {
			position2di mousepos = receiver.GetMouseState().Position;
			line3df ray = sceneManager->getSceneCollisionManager()->getRayFromScreenCoordinates( mousepos, camera);

			vector3df intersection;
			triangle3df tri;

            for(Planet& planet : planets) {
				ITriangleSelector* wselector = sceneManager->createTriangleSelectorFromBoundingBox(planet.node);
				if (collisionManager->getCollisionPoint(ray, wselector, intersection, tri, planet.node)) {
					selectedNode = planet.node;
				}
				wselector->drop();
			}
		}

		camera->setTarget(selectedNode->getAbsolutePosition());

		skybox->setVisible(true);		
        
		driver->setViewPort(mainCameraViewPortRect);
		driver->beginScene(true, true, SColor(255,100,101,140));
		sceneManager->setActiveCamera(camera);
		sceneManager->drawAll();
		guiEnv->drawAll();

		driver->setViewPort(rect<s32>(0, 380, 200, 600));
		driver->draw2DRectangle(SColor(100,0,0,190), mainCameraViewPortRect);
		skybox->setVisible(false);		
		sceneManager->setActiveCamera(topViewCamera);
		sceneManager->drawAll();
		
		driver->endScene();
	}
	device->drop();

	return EXIT_SUCCESS;
}