// Copyright (C) 2013 Jérôme Leclercq // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp #include #include #include #include #include #include #include #include #include #include #include #include #include struct NzSceneImpl { NzSceneImpl(NzScene* scene) : root(scene) { } std::unique_ptr renderTechnique; std::unique_ptr background; std::vector updateList; std::vector visibleUpdateList; NzClock updateClock; NzColor ambientColor = NzColor(25,25,25); NzSceneRoot root; NzCamera* activeCamera; bool update; float frameTime; float updateTime; unsigned int updatePerSecond = 60; }; NzScene::NzScene() { m_impl = new NzSceneImpl(this); m_impl->background.reset(new NzColorBackground); m_impl->renderTechnique.reset(new NzForwardRenderTechnique); } NzScene::~NzScene() { for (NzNode* child : m_impl->root.GetChilds()) { if (child->GetNodeType() == nzNodeType_Scene) static_cast(child)->SetScene(nullptr); } delete m_impl; } void NzScene::AddToVisibilityList(NzUpdatable* object) { m_impl->visibleUpdateList.push_back(object); } void NzScene::Cull() { NzAbstractRenderQueue* renderQueue = m_impl->renderTechnique->GetRenderQueue(); renderQueue->Clear(); m_impl->visibleUpdateList.clear(); // Frustum culling RecursiveFrustumCull(renderQueue, m_impl->activeCamera->GetFrustum(), &m_impl->root); ///TODO: Occlusion culling ///TODO: Light culling } void NzScene::Draw() { m_impl->renderTechnique->Clear(this); m_impl->renderTechnique->Draw(this); } NzCamera* NzScene::GetActiveCamera() const { return m_impl->activeCamera; } NzColor NzScene::GetAmbientColor() const { return m_impl->ambientColor; } NzBackground* NzScene::GetBackground() const { return m_impl->background.get(); } NzAbstractRenderTechnique* NzScene::GetRenderTechnique() const { return m_impl->renderTechnique.get(); } NzSceneNode& NzScene::GetRoot() const { return m_impl->root; } float NzScene::GetUpdateTime() const { return m_impl->updateTime; } unsigned int NzScene::GetUpdatePerSecond() const { return m_impl->updatePerSecond; } void NzScene::RegisterForUpdate(NzUpdatable* object) { #if NAZARA_GRAPHICS_SAFE if (!object) { NazaraError("Invalid object"); return; } #endif m_impl->updateList.push_back(object); } void NzScene::SetAmbientColor(const NzColor& color) { m_impl->ambientColor = color; } void NzScene::SetBackground(NzBackground* background) { m_impl->background.reset(background); } void NzScene::SetRenderTechnique(NzAbstractRenderTechnique* renderTechnique) { m_impl->renderTechnique.reset(renderTechnique); } void NzScene::SetUpdatePerSecond(unsigned int updatePerSecond) { m_impl->updatePerSecond = updatePerSecond; } void NzScene::UnregisterForUpdate(NzUpdatable* object) { #if NAZARA_GRAPHICS_SAFE if (!object) { NazaraError("Invalid object"); return; } #endif auto it = std::find(m_impl->updateList.begin(), m_impl->updateList.end(), object); if (it != m_impl->updateList.end()) m_impl->updateList.erase(it); } void NzScene::Update() { m_impl->update = (m_impl->updatePerSecond == 0 || m_impl->updateClock.GetMilliseconds() > 1000/m_impl->updatePerSecond); if (m_impl->update) { m_impl->updateTime = m_impl->updateClock.GetSeconds(); m_impl->updateClock.Restart(); for (NzUpdatable* updatable : m_impl->updateList) ///TODO: Multihreading updatable->Update(); } } void NzScene::UpdateVisible() { if (m_impl->update) { for (NzUpdatable* node : m_impl->visibleUpdateList) node->Update(); } } NzScene::operator const NzSceneNode&() const { return m_impl->root; } void NzScene::RecursiveFrustumCull(NzAbstractRenderQueue* renderQueue, const NzFrustumf& frustum, NzNode* node) { for (NzNode* child : node->GetChilds()) { if (child->GetNodeType() == nzNodeType_Scene) { NzSceneNode* sceneNode = static_cast(child); ///TODO: Empêcher le rendu des enfants si le parent est cullé selon un flag sceneNode->UpdateVisibility(frustum); if (sceneNode->IsVisible()) sceneNode->AddToRenderQueue(renderQueue); } if (child->HasChilds()) RecursiveFrustumCull(renderQueue, frustum, child); } } void NzScene::SetActiveCamera(NzCamera* camera) { m_impl->activeCamera = camera; }