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); } } } }
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); } } } }
/** * @brief * Called when the scene node assigned with this visibility container was destroyed */ void VisContainer::OnDestroy() { SceneNode *pSceneNode = GetSceneNode(); if (pSceneNode && pSceneNode->IsContainer()) { // Get the parent visibility container const VisNode *pParent = GetParent(); if (pParent && pParent->IsContainer()) { VisContainer *pParentVisContainer = const_cast<VisContainer*>(static_cast<const VisContainer*>(pParent)); // Unregister within the parent container VisContainer *pContainer = pParentVisContainer->m_mapContainers.Get(pSceneNode->GetName()); if (pContainer) { pParentVisContainer->m_lstNodes.Remove(pContainer); delete pContainer; pParentVisContainer->m_mapContainers.Remove(pSceneNode->GetName()); } } } }
/** * @brief * Post draw all scene nodes recursive */ void SPScene::DrawPost(Renderer &cRenderer, SceneContainer &cContainer) { // Get the scene container (can be a null pointer) SceneContainer *pContainer = GetSceneContainer(); // Draw parent container if (&cContainer != pContainer) cContainer.DrawPost(cRenderer); // Loop through all nodes for (uint32 i=0; i<cContainer.GetNumOfElements(); i++) { SceneNode *pNode = cContainer.GetByIndex(i); if (pNode != pContainer && pNode->IsVisible() && (pNode->GetDrawFunctionFlags() & SceneNode::UseDrawPost)) { if (pNode->IsContainer()) DrawPost(cRenderer, static_cast<SceneContainer&>(*pNode)); else pNode->DrawPost(cRenderer); } } }
/** * @brief * Function that is called to create the application's root scene */ void SceneApplication::OnCreateRootScene() { // [TODO] Load 'm_sSceneFilename' if provided // Is there a scene context? if (m_pSceneContext) { // First, create the scene root container which holds the scene container with our 'concrete' scene within it SceneContainer *pRootContainer = m_pSceneContext->GetRoot() ? static_cast<SceneContainer*>(m_pSceneContext->GetRoot()->Create("PLScene::SceneContainer", "RootScene")) : nullptr; if (pRootContainer) { // Protect this important container! pRootContainer->SetProtected(true); // Create a scene container with our 'concrete scene' SceneNode *pSceneContainerNode = pRootContainer->Create("PLScene::SceneContainer", "Scene"); if (pSceneContainerNode && pSceneContainerNode->IsContainer()) { // Protect this important container! pSceneContainerNode->SetProtected(true); } } // Set the root scene SetRootScene(pRootContainer); } }
//[-------------------------------------------------------] //[ 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); } }
/** * @brief * Recursive part of PerformQuery() */ bool SQPlaneSet::PerformQueryRec(SceneHierarchyNode &cHierarchyNode) { // Is this scene hierarchy node intersecting the plane set? if (!cHierarchyNode.CheckPlaneSet(m_cPlaneSet)) return true; // Continue the query // Touch this node cHierarchyNode.Touch(); // Get the scene context SceneContext *pSceneContext = GetSceneContext(); if (pSceneContext) { // Inform all listeners const SceneHierarchyNodeItem *pItem = cHierarchyNode.GetFirstItem(); while (pItem) { // Get the linked scene node SceneNode *pSceneNode = pItem->GetSceneNode(); // Was this scene node already processed? if (pSceneNode && !pSceneContext->IsNodeTouched(*pSceneNode)) { // Check scene node const AABoundingBox &cAABB = pSceneNode->GetContainerAABoundingBox(); if (Intersect::PlaneSetAABox(m_cPlaneSet, cAABB.vMin, cAABB.vMax)) { // Touch this node pSceneContext->TouchNode(*pSceneNode); // Emit signal SignalSceneNode(*this, *pSceneNode); if (m_nFlags & StopQuery) return false; // Stop the query right now // Continue recursive? if (m_nFlags & Recursive) { // Is this a container and is recursion allowed? if (pSceneNode->IsContainer() && !(pSceneNode->GetFlags() & SceneContainer::NoRecursion)) { // Backup current plane set const PlaneSet cPlaneSet = m_cPlaneSet; // Transform the plane set into container space m_cPlaneSet *= pSceneNode->GetTransform().GetInverseMatrix(); // Container recursion const bool bContinue = PerformQueryRec(static_cast<SceneContainer*>(pSceneNode)->GetHierarchyInstance()->GetRootNode()); // Restore plane set m_cPlaneSet = cPlaneSet; // Stop the query right now? if (!bContinue) return false; // Is this a cell-portal? } else if (pSceneNode->IsPortal() && pSceneNode->IsInstanceOf("PLScene::SNCellPortal") && !(pSceneNode->GetFlags() & SNCellPortal::NoPassThrough)) { // Get the target cell SNCellPortal &cCellPortal = static_cast<SNCellPortal&>(*pSceneNode); SceneContainer *pCell = reinterpret_cast<SceneContainer*>(cCellPortal.GetTargetCellInstance()); if (pCell && pCell != pSceneNode->GetContainer()) { // Backup current plane set const PlaneSet cPlaneSet = m_cPlaneSet; // Transform the plane set into container space m_cPlaneSet *= cCellPortal.GetWarpMatrix(); // Container recursion const bool bContinue = PerformQueryRec(pCell->GetHierarchyInstance()->GetRootNode()); // Restore plane set m_cPlaneSet = cPlaneSet; // Stop the query right now? if (!bContinue) return false; } } } } } // Next item, please pItem = pItem->GetNextItem(); } } // Check all sub-hierarchies for (uint32 i=0; i<cHierarchyNode.GetNumOfNodes(); i++) { if (!PerformQueryRec(*cHierarchyNode.GetNode(i))) return false; // Stop the query right now } // Done, continue the query return true; }