/**
*  @brief
*    Sets the used scene renderer
*/
bool SceneRendererTool::SetSceneRenderer(SceneContainer *pSceneContainer, const String &sFilename, const String &sFallbackFilename)
{
	// Is there a surface painter and is it an "SPScene"-instance?
	if (pSceneContainer && m_pSurfacePainter && m_pSurfacePainter->IsInstanceOf("PLScene::SPScene")) {
		// Get and setup the "SPScene"-instance of the surface painter
		SPScene *pSPScene = static_cast<SPScene*>(m_pSurfacePainter);
		pSPScene->SetRootContainer(pSceneContainer->GetContainer());
		pSPScene->SetSceneContainer(pSceneContainer);

		// Check renderer API and version number, if legacy hardware is used we can only
		// use a quite primitive scene renderer!
		String sSceneRendererFilename = sFilename;
		{
			// [TODO] Detect required capabilities of a scene renderer? (important)

			// OpenGL
			uint32 nVersion = 0;
			if (m_pSurfacePainter->GetRenderer().GetAPI(&nVersion) == "OpenGL") {
				if (nVersion < 14) {
					sSceneRendererFilename = sFallbackFilename;
					PL_LOG(Warning, "Your graphics card is too old to support proper shader rendering. "
									"At least a OpenGL 1.4 compatible graphics card is recommended. A fallback fill be used.")
				}

			// OpenGL ES 2.0
			} else if (m_pSurfacePainter->GetRenderer().GetAPI(&nVersion) == "OpenGL ES 2.0") {
void SCRenderToTexture::SetPainter(const String &sValue)
{
	if (m_sPainter != sValue) {
		m_sPainter = sValue;

		// Setup the surface painter
		if (m_pSurfaceTextureBuffer) {
			SurfacePainter *pSurfacePainter = GetSceneContext()->GetRendererContext().GetRenderer().CreateSurfacePainter(m_sPainter);
			m_pSurfaceTextureBuffer->SetPainter(pSurfacePainter);
			if (pSurfacePainter && pSurfacePainter->IsInstanceOf("PLScene::SPScene")) {
				// Do NOT let the renderer update this surface by default, WE update it inside DrawPre()
				m_pSurfaceTextureBuffer->SetActive(false);

				// THIS is the scene root :)
				SPScene *pPainter = static_cast<SPScene*>(pSurfacePainter);
				pPainter->SetRootContainer(this);

				// Tell the surface scene painter about the 'conrete scene'
				SceneNode *pSceneNode = GetByName(m_sSceneName);
				if (pSceneNode && pSceneNode->IsContainer())
					pPainter->SetSceneContainer(static_cast<SceneContainer*>(pSceneNode));
				else
					pPainter->SetSceneContainer(nullptr);

				// Set default scene renderer
				pPainter->SetDefaultSceneRenderer(m_sSceneRenderer);
			}
		}
	}
}
//[-------------------------------------------------------]
//[ Private virtual PLEngine::EngineApplication functions ]
//[-------------------------------------------------------]
void Application65::OnCreateScene(SceneContainer &cContainer)
{
	// Create a scene node with the soldier mesh
	cContainer.Create("PLScene::SNMesh", "Soldier", "Position=\"0.0 -0.7 -4.0\" Scale=\"0.008 0.008 0.008\" Mesh=\"Data/Meshes/Soldier.mesh\"");

	// Create a nice particle effect behind the soldier
	cContainer.Create("PLParticleGroups::PGMagic2", "Magic2", "Position=\"0.0 0.0 -25.0\"");

	// Create a moving light source to illuminate the scene
	cContainer.Create("PLScene::SNPointLight", "Light", "Position=\"1.0 2.0 -2.0\" Flags=\"Flares|Corona|Blend\" Range=\"15.0\"");

	// Create a camera - this time we increase the camera FOV to get a better space feeling :)
	SceneNode *pCamera = cContainer.Create("PLScene::SNCamera", "FixedCamera", "Position=\"0.0 0.0 -2.5\" Rotation=\"0.0 180.0 0.0\" FOV=\"60\"");
	if (pCamera && pCamera->IsInstanceOf("PLScene::SNCamera")) {
		// Make this to our main scene camera
		SetCamera(reinterpret_cast<SNCamera*>(pCamera));

		// Get class list of all available post process scene node modifiers
		m_lstModifierClasses.Clear();
		ClassManager::GetInstance()->GetClasses(m_lstModifierClasses, "PLCompositing::SNMPostProcess", Recursive, NoBase, NoAbstract);

		// 'Activate' the first effect
		if (m_lstModifierClasses.GetNumOfElements())
			pCamera->AddModifier(m_lstModifierClasses[m_nCurrentSelectedModifier]->GetClassName());
	}

	// Setup scene surface painter
	SurfacePainter *pPainter = GetPainter();
	if (pPainter && pPainter->IsInstanceOf("PLScene::SPScene")) {
		SPScene *pSPScene = static_cast<SPScene*>(pPainter);
		pSPScene->SetRootContainer(cContainer.GetContainer());
		pSPScene->SetSceneContainer(&cContainer);
	}

	// Within the parent container...
	SceneContainer *pContainer = cContainer.GetContainer();
	if (pContainer) {
		// Add our information text scene nodes
		SceneNode *pInfoText = pContainer->Create("PLScene::SceneContainer", "InfoText", "Flags=\"NoCulling\"");
		if (pInfoText && pInfoText->IsInstanceOf("PLScene::SceneContainer")) {
			SceneContainer *pInfoTextContainer = static_cast<SceneContainer*>(pInfoText);
			pInfoTextContainer->Create("PLScene::SNText2D", '0', "Position=\"0.01 0.01\" Flags=\"No3DPosition|NoCenter\" Text=\"" + PLT("'F1'        = Show/hide this help text")       + '\"');
			pInfoTextContainer->Create("PLScene::SNText2D", '1', "Position=\"0.01 0.03\" Flags=\"No3DPosition|NoCenter\" Text=\"" + PLT("'Space'     = Enable/disable post processing") + '\"');
			pInfoTextContainer->Create("PLScene::SNText2D", '2', "Position=\"0.01 0.05\" Flags=\"No3DPosition|NoCenter\" Text=\"" + PLT("'1-7'       = Custom post process effects")    + '\"');
			pInfoTextContainer->Create("PLScene::SNText2D", '3', "Position=\"0.01 0.07\" Flags=\"No3DPosition|NoCenter\" Text=\"" + PLT("'Page up'   = Next post process effect")       + '\"');
			pInfoTextContainer->Create("PLScene::SNText2D", '4', "Position=\"0.01 0.09\" Flags=\"No3DPosition|NoCenter\" Text=\"" + PLT("'Page down' = Previous post process effect")   + '\"');
		}
	}

	// Set scene container
	SetScene(&cContainer);
}
Beispiel #4
0
//[-------------------------------------------------------]
//[ Private virtual PLEngine::EngineApplication functions ]
//[-------------------------------------------------------]
void Application67::OnCreateScene(SceneContainer &cContainer)
{
	// Create a scene container with our 'concrete sound scene' using the default sound API
	SceneNode *pSceneContainerNode = cContainer.Create("PLSound::SCSound", "SoundScene");
	if (pSceneContainerNode && pSceneContainerNode->IsInstanceOf("PLScene::SceneContainer")) {
		SceneContainer *pSceneContainer = static_cast<SceneContainer*>(pSceneContainerNode);

		// Protect this important container!
		pSceneContainer->SetProtected(true);

		// Populate the scene container
		// Setup scene surface painter
		SurfacePainter *pPainter = GetPainter();
		if (pPainter && pPainter->IsInstanceOf("PLScene::SPScene")) {
			SPScene *pSPScene = static_cast<SPScene*>(pPainter);
			pSPScene->SetRootContainer(cContainer.GetContainer());
			pSPScene->SetSceneContainer(pSceneContainer);

			// Get the scene context
			SceneContext *pSceneContext = GetSceneContext();
			if (pSceneContext) {
				// Create us a scene renderer
				SceneRenderer *pSceneRenderer = pSceneContext->GetSceneRendererManager().Create("2DGame");
				if (pSceneRenderer) {
					// Add begin scene renderer pass
					pSceneRenderer->Create("PLCompositing::SRPBegin", "Begin", "TextureFormat=\"R8G8B8A8\" Flags=\"Inactive\"");

					// Add our own scene renderer pass
					pSceneRenderer->Create("SRP2DGame", "2DGame");

					// Add post processing scene renderer pass
					pSceneRenderer->Create("PLCompositing::SRPPostProcessing", "PostProcessing");

					// Add end scene renderer pass
					pSceneRenderer->Create("PLCompositing::SRPEnd", "End");

					// Make this scene renderer to the default scene renderer of our scene surface painter
					pSPScene->SetDefaultSceneRenderer(pSceneRenderer->GetName());
				}
			}
		}

		// Set scene container
		SetScene(pSceneContainer);

		// Start the game
		Restart();
	}
}
void SCRenderToTexture::SetSceneRenderer(const String &sValue)
{
	if (m_sSceneRenderer != sValue) {
		m_sSceneRenderer = sValue;

		// Setup the surface painter
		if (m_pSurfaceTextureBuffer) {
			SurfacePainter *pSurfacePainter = m_pSurfaceTextureBuffer->GetPainter();
			if (pSurfacePainter && pSurfacePainter->IsInstanceOf("PLScene::SPScene")) {
				SPScene *pPainter = static_cast<SPScene*>(pSurfacePainter);
				pPainter->SetDefaultSceneRenderer(m_sSceneRenderer);
			}
		}
	}
}
Beispiel #6
0
//[-------------------------------------------------------]
//[ Private virtual PLEngine::EngineApplication functions ]
//[-------------------------------------------------------]
void Application66::OnCreateScene(SceneContainer &cContainer)
{
	// Set scene container flags
	cContainer.SetFlags(SceneNode::NoCulling);

	// Setup scene surface painter
	SurfacePainter *pPainter = GetPainter();
	if (pPainter && pPainter->IsInstanceOf("PLScene::SPScene")) {
		SPScene *pSPScene = static_cast<SPScene*>(pPainter);
		pSPScene->SetRootContainer(cContainer.GetContainer());
		pSPScene->SetSceneContainer(&cContainer);
	}

	// Within the parent container...
	SceneContainer *pContainer = cContainer.GetContainer();
	if (pContainer) {
		// Create a 'ingame'-GUI scene node
		const SNGui *pGuiSceneNode = static_cast<SNGui*>(pContainer->Create("PLFrontendPLGui::SNGui", "GUI"));
		if (pGuiSceneNode) {
			// Setup the GUI
			Gui *pGui = pGuiSceneNode->GetGui();
			if (pGui) {
				// Create the GUI font
				if (!GuiFont) {
					GuiFont = new Font(*pGui);
					GuiFont->LoadFromFile("Data/Fonts/LinLibertine_Re-2.7.9.9.otf", 18);
				}

				// Set GUI options
				pGui->SetMouseVisible(false);

				// Create ingame GUI container
				m_pIngameGui = new IngameGui(*this, pGui->GetRootWidget());
				m_pIngameGui->SetSize(Vector2i(1024, 768));
				m_pIngameGui->SetBackgroundColor(PLGraphics::Color4::Transparent);
				m_pIngameGui->SetFocus();
				m_pIngameGui->SetVisible(true);
			}
		}
	}

	// Set scene container
	SetScene(&cContainer);
}
void SCRenderToTexture::SetSceneName(const String &sValue)
{
	if (m_sSceneName != sValue) {
		m_sSceneName = sValue;

		// Setup the surface painter
		if (m_pSurfaceTextureBuffer) {
			SurfacePainter *pSurfacePainter = m_pSurfaceTextureBuffer->GetPainter();
			if (pSurfacePainter && pSurfacePainter->IsInstanceOf("PLScene::SPScene")) {
				SPScene *pPainter = static_cast<SPScene*>(pSurfacePainter);
				SceneNode *pSceneNode = GetByName(m_sSceneName);
				if (pSceneNode && pSceneNode->IsContainer())
					pPainter->SetSceneContainer(static_cast<SceneContainer*>(pSceneNode));
				else
					pPainter->SetSceneContainer(nullptr);
			}
		}
	}
}
//[-------------------------------------------------------]
//[ Private virtual PLEngine::EngineApplication functions ]
//[-------------------------------------------------------]
void Application70::OnCreateScene(SceneContainer &cContainer)
{
	// Create a camera
	SceneNode *pCamera = cContainer.Create("PLScene::SNCamera", "FreeCamera", "Position=\"1 2 -3\" Rotation=\"25 210 0\"");
	if (pCamera && pCamera->IsInstanceOf("PLScene::SNCamera")) {
		// Make this to our main scene camera
		SetCamera(reinterpret_cast<SNCamera*>(pCamera));

		// Add a controller modifier so we can look around the camera by using a default control
		pCamera->AddModifier("PLEngine::SNMEgoLookController");

		// Add a controller modifier so we can move around the camera by using a default control
		pCamera->AddModifier("PLEngine::SNMMoveController");
	}

	// Create the floor
	cContainer.Create("PLScene::SNMesh", "Floor", "Position=\"0 0 -5\" Scale=\"4 0.1 4\" Mesh=\"Default\"");

	// Create an instance of the fire particle effect scene node
	cContainer.Create("SNFireSample", "Fire", "Position=\"0.5 0.3 -5\" Scale=\"0.1 0.1 0.1\"");

	// Create an instance of the basic particle effect scene node
	cContainer.Create("SNBasicSample", "Basic", "Position=\"-0.5 0.1 -8\" Scale=\"0.5 0.5 0.5\"");

	// Create an instance of the gravitation particle effect scene node
	cContainer.Create("SNGravitationSample", "Gravitation", "Position=\"-1 1 -5\" Scale=\"0.5 0.5 0.5\"");

	// Create an instance of the galaxy particle effect scene node
	cContainer.Create("SNGalaxySample", "Galaxy", "Position=\"-3 0.5 -8\" Scale=\"0.5 0.5 0.5\"");

	// Setup scene surface painter
	SurfacePainter *pPainter = GetPainter();
	if (pPainter && pPainter->IsInstanceOf("PLScene::SPScene")) {
		SPScene *pSPScene = static_cast<SPScene*>(pPainter);
		pSPScene->SetRootContainer(cContainer.GetContainer());
		pSPScene->SetSceneContainer(&cContainer);
	}

	// Set scene container
	SetScene(&cContainer);
}
/**
*  @brief
*    Function that is called to create the application's scene container
*/
void EngineApplication::OnCreateScene(SceneContainer &cContainer)
{
	// [TODO] Load 'm_sSceneFilename' if provided

	// Set scene container flags
	cContainer.SetFlags(SceneNode::NoCulling);

	// Setup scene surface painter
	SurfacePainter *pPainter = GetPainter();
	if (pPainter && pPainter->IsInstanceOf("PLScene::SPScene")) {
		SPScene *pSPScene = static_cast<SPScene*>(pPainter);
		pSPScene->SetRootContainer(cContainer.GetContainer());
		pSPScene->SetSceneContainer(&cContainer);
	}

	// Configure scene and set the currently used application camera
	SetCamera(SceneCreator::ConfigureScene(cContainer, "PLEngine::SceneCreatorDefault"));

	// Set scene container
	SetScene(&cContainer);
}
//[-------------------------------------------------------]
//[ Private virtual PLEngine::EngineApplication functions ]
//[-------------------------------------------------------]
void Application64::OnCreateScene(SceneContainer &cContainer)
{
	// Create a camera
	SceneNode *pCamera = cContainer.Create("PLScene::SNCamera", "FreeCamera", "Position=\"1 2 -3\" Rotation=\"25 210 0\"");
	if (pCamera && pCamera->IsInstanceOf("PLScene::SNCamera")) {
		// Make this to our main scene camera
		SetCamera(reinterpret_cast<SNCamera*>(pCamera));
	}

	// Create a scene node with the soldier mesh - in debug mode, show some fancy technical visualizations
	SceneNode *pSceneNode = cContainer.Create("PLScene::SNMesh", "Soldier", "Position=\"0.0 0.1 -5.0\" Scale=\"0.008 0.008 0.008\" Mesh=\"Data/Meshes/Soldier.mesh\" DebugFlags=\"DebugShowWireframe|DebugShowJoints|DebugShowJointNames|DebugShowSkeleton\"");
	if (pSceneNode) {
		// Rotate the soldier
		pSceneNode->AddModifier("PLScene::SNMRotationLinearAnimation", "Velocity=\"0 10 0\"");

		// Playback the animation named "walk_0" letting the soldier walk
		pSceneNode->AddModifier("PLScene::SNMMeshAnimation", "Name=\"walk_0\"");

		// Animate the morph target named "blink" letting the soldier blink from time to time
		pSceneNode->AddModifier("PLScene::SNMMeshMorphBlink", "Name=\"blink\"");
	}

	// Create the floor
	cContainer.Create("PLScene::SNMesh", "Floor", "Position=\"0.0 0.0 -5.0\" Rotation=\"0.0 180.0 0.0\" Scale=\"4.0 0.1 4.0\" Mesh=\"Default\"");

	// Setup scene surface painter
	SurfacePainter *pPainter = GetPainter();
	if (pPainter && pPainter->IsInstanceOf("PLScene::SPScene")) {
		SPScene *pSPScene = static_cast<SPScene*>(pPainter);
		pSPScene->SetRootContainer(cContainer.GetContainer());
		pSPScene->SetSceneContainer(&cContainer);
	}

	// Set scene container
	SetScene(&cContainer);

	// Create the picking component
	m_pMyPicking = new MyPicking(*this);
}
//[-------------------------------------------------------]
//[ Private virtual PLEngine::EngineApplication functions ]
//[-------------------------------------------------------]
void Application61::OnCreateScene(SceneContainer &cContainer)
{
	// Set no scene container as default
	SetScene(nullptr);

	// Sound API given?
	if (m_sSoundAPI.GetLength()) {
		// Create a scene container with our 'concrete sound scene' using the chosen sound API
		SceneNode *pSceneContainerNode = cContainer.Create("PLSound::SCSound", "SoundScene", "SoundAPI=\"" + m_sSoundAPI + "\" Pitch=\"" + Timing::GetInstance()->GetTimeScaleFactor() + '\"');
		if (pSceneContainerNode && pSceneContainerNode->IsInstanceOf("PLScene::SceneContainer")) {
			SceneContainer *pSceneContainer = static_cast<SceneContainer*>(pSceneContainerNode);

			// Protect this important container!
			pSceneContainer->SetProtected(true);

			// Set scene container
			SetScene(pSceneContainer);

			// Populate the scene container
			// Create a camera
			SceneNode *pCamera = pSceneContainer->Create("PLScene::SNCamera", "FreeCamera", "Position=\"0.0 -1.5 1.4\" Rotation=\"-14.0 180.0 0.0\"");
			if (pCamera && pCamera->IsInstanceOf("PLScene::SNCamera")) {
				// Make this to our main scene camera
				SetCamera(reinterpret_cast<SNCamera*>(pCamera));

				// Add a controller modifier so we can look around the camera by using a default control
				pCamera->AddModifier("PLEngine::SNMEgoLookController");

				// Add a controller modifier so we can move around the camera by using a default control
				pCamera->AddModifier("PLEngine::SNMMoveController", "Speed=\"2\"");

				// Make this camera to the 'sound listener'
				pSceneContainer->SetAttribute("Listener", pCamera->GetName());
			}

			// Create the floor
			pSceneContainer->Create("PLScene::SNMesh", "Floor", "Position=\"0.0 -2.1 -5.0\" Rotation=\"0.0 180.0 0.0\" Scale=\"4.0 0.1 4.0\" Mesh=\"Default\"");

			// Create a box on the floor
			pSceneContainer->Create("PLScene::SNMesh", "Box", "Position=\"0.0 -1.5 -5.0\" Scale=\"0.5 0.5 0.5\" Mesh=\"Default\"");

			// Create rain particles and rain sound
			pSceneContainer->Create("PLParticleGroups::PGRain", "Rain", "Position=\"0.0 15.0 -5.0\" Flags=\"ForceUpdate\" MediumSize=\"3\"");
			pSceneContainer->Create("PLSound::SNSound", "RainSound", "Sound=\"Data/Sounds/Rain.ogg\" Volume=\"0.2\"");

			// Create the soldier walking in the rain :)
			SceneNode *pSoldier = pSceneContainer->Create("PLScene::SNMesh", "Soldier", "Position=\"0.0 -1.5 -5.0\" Scale=\"0.007 0.007 0.007\" Mesh=\"Data/Meshes/Soldier.mesh\"");
			if (pSoldier) {
				// Add animation modifier
				pSoldier->AddModifier("PLScene::SNMMeshAnimation", "Name=\"walk_0\" Speed=\"2\"");

				// Let the soldier walk on a path...
				pSoldier->AddModifier("PLScene::SNMPositionPath", "Filename=\"Data/Misc/61Sound_Soldier.path\" Speed=\"0.5\" Flags=\"NodeIndexProgress\" Interpolation=\"CatmullRomCurve\"");

				// ... and we should look into the direction he's moving
				pSoldier->AddModifier("PLScene::SNMRotationMoveDirection");

				// Link a footsteps sound to the soldier
				pSoldier->AddModifier("PLSound::SNMSound","Sound=\"Data/Sounds/Walking.ogg\"");
			}

			// Setup scene surface painter
			SurfacePainter *pPainter = GetPainter();
			if (pPainter && pPainter->IsInstanceOf("PLScene::SPScene")) {
				SPScene *pSPScene = static_cast<SPScene*>(pPainter);
				pSPScene->SetRootContainer(cContainer.GetContainer());
				pSPScene->SetSceneContainer(pSceneContainer);
			}

			// Within the parent container...
			SceneContainer *pContainer = pSceneContainer->GetContainer();
			if (pContainer) {
				// Get/add our information text scene nodes
				SceneNode *pInfoText = pContainer->Create("PLScene::SceneContainer", "InfoText", "Flags=\"NoCulling\"");
				if (pInfoText && pInfoText->IsInstanceOf("PLScene::SceneContainer")) {
					SceneContainer *pInfoTextContainer = static_cast<SceneContainer*>(pInfoText);

					// The name of the used sound API
					pInfoTextContainer->Create("PLScene::SNText2D", "SoundAPI", "Position=\"0.01 0.01\" Flags=\"No3DPosition|NoCenter\" Text=\"" + PLT("Sound API: ") + GetSoundAPI() + '\"');

					// Draw keys information
					pInfoTextContainer->Create("PLScene::SNText2D", "Keys",      "Position=\"0.01 0.04\" Flags=\"No3DPosition|NoCenter\" Text=\"" + PLT("Keys:")                      + '\"');
					pInfoTextContainer->Create("PLScene::SNText2D", "TimeScale", "Position=\"0.06 0.08\" Flags=\"No3DPosition|NoCenter\"");
					UpdateTimeScaleTextNode();
				}
			}
		}
	}
}
//[-------------------------------------------------------]
//[ Public virtual SceneNode functions                    ]
//[-------------------------------------------------------]
void SCRenderToTexture::DrawPre(Renderer &cRenderer, const VisNode *pVisNode)
{
	if (IsActive() && m_pSurfaceTextureBuffer) {
		// Call base implementation
		SceneContainer::DrawPre(cRenderer, pVisNode);

		// Check FPS limitation
		if (FPSLimit) {
			const uint64 nCurrentTime = System::GetInstance()->GetMilliseconds();
			if (m_nFPSLimitLastTime && nCurrentTime-m_nFPSLimitLastTime < static_cast<uint64>(1000.0f/FPSLimit))
				return; // Do not update
			m_nFPSLimitLastTime = nCurrentTime;
		}

		// Get the surface scene painter
		SurfacePainter *pSurfacePainter = m_pSurfaceTextureBuffer->GetPainter();
		if (pSurfacePainter && pSurfacePainter->IsInstanceOf("PLScene::SPScene")) {
			SPScene *pPainter = static_cast<SPScene*>(pSurfacePainter);

			// Deactivate THIS node to avoid recursion
			SetActive(false);

			// Get current camera
			SNCamera *pCameraBackup = SNCamera::GetCamera();

			// Set camera
			SceneNode *pSceneNode = GetByName(CameraName.Get());
			if (pSceneNode && pSceneNode->IsCamera()) {
				// If the camera is not active, we do not need to do anything in here...
				if (!pSceneNode->IsActive())
					return;

				pPainter->SetCamera(static_cast<SNCamera*>(pSceneNode));
				static_cast<SNCamera*>(pSceneNode)->SetCamera(cRenderer);
			} else
				pPainter->SetCamera(nullptr);

			// Get current render target
			Surface *pSurfaceBackup = cRenderer.GetRenderTarget();


			// [HACK] If the painter has no scene container, check if the scene container exists now...
			if (!pPainter->GetSceneContainer()) {
				pSceneNode = GetByName(m_sSceneName);
				if (pSceneNode && pSceneNode->IsContainer())
					pPainter->SetSceneContainer(static_cast<SceneContainer*>(pSceneNode));
			}


			// Check the render target type
			if (m_bCube) { // Render to cube texture
				// Setup the camera
				SNCamera *pCamera = pPainter->GetCamera();
				if (pCamera) {
					// Set field of view and aspect
					pCamera->SetFOV(90.0f);
					pCamera->SetAspect(1.0f);

					// For each of the 6 cube faces...
					for (uint8 nFace=0; nFace<6; nFace++) {
						// Set rotation
						switch (nFace) {
							// x-positive
							case 0:
								pCamera->SetRotation(Vector3(  0.0f, -90.0f, 180.0f));
								break;

							// x-negative
							case 1:
								pCamera->SetRotation(Vector3(  0.0f,  90.0f, 180.0f));
								break;

							// y-positive
							case 2:
								pCamera->SetRotation(Vector3( 90.0f,   0.0f, 180.0f));
								break;

							// y-negative
							case 3:
								pCamera->SetRotation(Vector3(-90.0f,   0.0f, 180.0f));
								break;

							// z-positive
							case 4:
								pCamera->SetRotation(Vector3(  0.0f,   0.0f, 180.0f));
								break;

							// z-negative
							case 5:
								pCamera->SetRotation(Vector3(  0.0f, 180.0f, 180.0f));
								break;
						}

						// Set the new render target
						if (cRenderer.SetRenderTarget(m_pSurfaceTextureBuffer, nFace)) {
							// Draw a nice and colorful picture :)
							pPainter->OnPaint(*m_pSurfaceTextureBuffer);
						}
					}
				} else {
					// For each of the 6 cube faces...
					for (uint8 nFace=0; nFace<6; nFace++) {
						// Set the new render target
						if (cRenderer.SetRenderTarget(m_pSurfaceTextureBuffer, nFace)) {
							// Draw a nice and colorful picture :)
							pPainter->OnPaint(*m_pSurfaceTextureBuffer);
						}
					}
				}

			} else { // Render to 2D/rectangle texture
				// Set the new render target
				if (cRenderer.SetRenderTarget(m_pSurfaceTextureBuffer)) {
					// Draw a nice and colorful picture :)
					pPainter->OnPaint(*m_pSurfaceTextureBuffer);
				}
			}

			// Reset renderer target
			cRenderer.SetRenderTarget(pSurfaceBackup);
			if (pCameraBackup) {
				pPainter->SetCamera(pCameraBackup);
				pCameraBackup->SetCamera(cRenderer);
			}

			// Reactivate THIS node to avoid recursion
			SetActive(true);
		}
	}
}
/**
*  @brief
*    Creates/recreates the texture surface
*/
void SCRenderToTexture::CreateSurfaceTexture()
{
	// Get the renderer
	Renderer &cRenderer = GetSceneContext()->GetRendererContext().GetRenderer();

	// Delete the old render to texture buffer surface
	if (m_pSurfaceTextureBuffer) {
		delete m_pSurfaceTextureBuffer;
		m_pSurfaceTextureBuffer = nullptr;
	}

	// Delete the old resulting texture
	Texture *pTexture = m_pTextureHandler->GetResource();
	if (pTexture) {
		pTexture->Delete();
		m_pTextureHandler->SetResource(nullptr);
	}

	// Get the desired texture buffer format
	TextureBuffer::EPixelFormat nFormat;
	switch (m_nFormat) {
		case 0:
			nFormat = TextureBuffer::R8G8B8;
			break;

		case 1:
			nFormat = TextureBuffer::R8G8B8A8;
			break;

		default:
			nFormat = TextureBuffer::R8G8B8A8;
			break;
	}

	// Create 'render to texture buffer' surface
	if (m_bCube) {
		m_pSurfaceTextureBuffer = cRenderer.CreateSurfaceTextureBufferCube(m_nWidth, nFormat, m_nSurfaceFlags);
	} else {
		// If possible, we use a standard 2D texture buffer
		if (cRenderer.GetCapabilities().bTextureBufferNonPowerOfTwo || (Math::IsPowerOfTwo(m_nWidth) && Math::IsPowerOfTwo(m_nHeight)))
			m_pSurfaceTextureBuffer = cRenderer.CreateSurfaceTextureBuffer2D(Vector2i(m_nWidth, m_nHeight), nFormat, m_nSurfaceFlags);
		else
			m_pSurfaceTextureBuffer = cRenderer.CreateSurfaceTextureBufferRectangle(Vector2i(m_nWidth, m_nHeight), nFormat, m_nSurfaceFlags);
	}
	if (m_pSurfaceTextureBuffer) {
		// Setup the surface painter
		SurfacePainter *pSurfacePainter = cRenderer.CreateSurfacePainter(m_sPainter);
		m_pSurfaceTextureBuffer->SetPainter(pSurfacePainter);
		if (pSurfacePainter && pSurfacePainter->IsInstanceOf("PLScene::SPScene")) {
			// Do NOT let the renderer update this surface by default, WE update it inside DrawPre()
			m_pSurfaceTextureBuffer->SetActive(false);

			// THIS is the scene root :)
			SPScene *pPainter = static_cast<SPScene*>(pSurfacePainter);
			pPainter->SetRootContainer(this);

			// Tell the surface scene painter about the 'conrete scene'
			SceneNode *pSceneNode = GetByName(m_sSceneName);
			pPainter->SetSceneContainer((pSceneNode && pSceneNode->IsContainer()) ? static_cast<SceneContainer*>(pSceneNode) : nullptr);

			// Set default scene renderer
			pPainter->SetDefaultSceneRenderer(m_sSceneRenderer);
		}
	}

	// Add the texture
	TextureManager &cTextureManager = cRenderer.GetRendererContext().GetTextureManager();
	// If there's already a texture with this name we have to get another, still free resource name
	if (cTextureManager.GetByName(m_sTextureName)) {
		// Find an unused resource name
		String sName = m_sTextureName + "_0";
		for (uint32 i=1; cTextureManager.GetByName(sName); i++)
			sName = m_sTextureName + '_' + static_cast<int>(i);

		// We have found an unused name
		m_sTextureName = sName;
	}
	if (m_pSurfaceTextureBuffer && m_pSurfaceTextureBuffer->GetTextureBuffer()) {
		pTexture = cTextureManager.CreateTexture(m_sTextureName, *m_pSurfaceTextureBuffer->GetTextureBuffer());
		if (pTexture)
			m_sTextureName = pTexture->GetName();
		m_pTextureHandler->SetResource(pTexture);
	}
}