diff --git a/src/engine.cpp b/src/engine.cpp index 0abb007..f11f9fb 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -30,7 +30,6 @@ Engine::Engine() : m_clock = new sf::Clock(); m_clock->restart(); m_renderer = new SparrowRenderer(); - m_guiTools = new GuiTools(this); } Engine::~Engine() @@ -65,6 +64,7 @@ void Engine::createWindow(std::string title, m_input = new Input(m_window); m_renderer->initGL(w, h); m_sparrowshell = new SparrowShell(m_window); + m_guiTools = new GuiTools(); } void Engine::initPhysics() @@ -118,8 +118,6 @@ void Engine::update() ImGui::End(); } } - - m_guiTools->update(); // update Physics if(m_world != nullptr) @@ -134,6 +132,7 @@ void Engine::update() // update Scene getScene()->update(); + getScene()->updateShaders(); // update Display if(m_input->isResized()) @@ -181,10 +180,13 @@ void Engine::setScene(std::string scene) } previous_scene->getRootObject()->removeChild(m_sparrowshell); + previous_scene->getRootObject()->removeChild(m_guiTools); + m_renderer->setScene(new_scene); m_renderer->resizeGL(m_window->getSize().x, m_window->getSize().y); + new_scene->getRootObject()->addChild(m_sparrowshell); - new_scene->updateShaders(); + new_scene->getRootObject()->addChild(m_guiTools); } void Engine::enablePhysicsDebug() @@ -195,7 +197,6 @@ void Engine::enablePhysicsDebug() getScene()->addToIndex(m_physicsDebugNode); m_world->setDebugDrawer(m_physicsDebugNode); m_world->getDebugDrawer()->setDebugMode(btIDebugDraw::DBG_DrawWireframe); - getScene()->updateShaders(); } } @@ -269,7 +270,7 @@ void Engine::checkSpecialInputs() void Engine::createScene(std::string scene_name) { - RESOURCE_ADD(new SceneTree(*this),SceneTree,scene_name); + RESOURCE_ADD(new SceneTree(*this), SceneTree, scene_name); //return new SceneTree(*this); } diff --git a/src/guitools.cpp b/src/guitools.cpp index 883b3ba..a431ddd 100644 --- a/src/guitools.cpp +++ b/src/guitools.cpp @@ -2,51 +2,28 @@ #include "imgui/imgui.h" #include "engine.h" +#include "tools/scenepicker.h" #include "scene/scenetree.h" -#include "SparrowRenderer/deferredpipeline.h" -#include "scene/playercharacternode.h" -#include -#include -#include - -GuiTools::GuiTools(Engine* engine) : - m_engine(engine), +GuiTools::GuiTools() : + m_pickerNode(new ScenePicker()), m_pickerEnabled(false) { - + addChild(m_pickerNode); + m_pickerNode->setVisible(false); } void GuiTools::update() { + // no automatic update of children, we want to update them manually + // ContainerNode::update(); + if(m_pickerEnabled) - { - DeferredPipeline* pip = (DeferredPipeline*) m_engine->getScene()->getPipeline(); - FirstPersonCamera* cam = (FirstPersonCamera*) pip->getCamera(); - glm::vec3 dir_cam = cam->getDirection()*100; - btVector3 start(cam->getEyePosition().x,cam->getEyePosition().y,cam->getEyePosition().z); - btVector3 end(start.x() + dir_cam.x,start.y() + dir_cam.y,start.z() + dir_cam.z); - btCollisionWorld::ClosestRayResultCallback RayCallback(start, end); - m_engine->getPhysics()->rayTest(start,end,RayCallback); - - ImGui::Begin("Picker", &m_pickerEnabled); - if(RayCallback.hasHit()) - { - btVector3 target = RayCallback.m_hitPointWorld; - ImGui::Text("Target coordinates : (%.3f,%.3f,%.3f)",target.x(),target.y(),target.z()); - - } - else - { - ImGui::Text("Nothing"); - } - // if(ImGui::Button("Teleport")) - //move player to target coordinate - ImGui::End(); - } + m_pickerNode->update(); } void GuiTools::togglePicker() { m_pickerEnabled = !m_pickerEnabled; + m_pickerNode->setVisible(m_pickerEnabled); } diff --git a/src/guitools.h b/src/guitools.h index 6629278..b2c8da6 100644 --- a/src/guitools.h +++ b/src/guitools.h @@ -1,14 +1,17 @@ #ifndef GUITOOLS_H #define GUITOOLS_H -class Engine; +#include "scene/containernode.h" -class GuiTools +class Engine; +class ScenePicker; + +class GuiTools : public ContainerNode { - Engine* m_engine; + ScenePicker* m_pickerNode; bool m_pickerEnabled; public: - GuiTools(Engine*); + GuiTools(); void update(); void togglePicker(); }; diff --git a/src/scene/gibgeneratornode.cpp b/src/scene/gibgeneratornode.cpp index 963fcb5..d965aa7 100644 --- a/src/scene/gibgeneratornode.cpp +++ b/src/scene/gibgeneratornode.cpp @@ -26,7 +26,6 @@ void GibGeneratorNode::createGib(GraphicalNode* graphicalPart, m_gibs.push_back(new Gib(body, graphicalPart, getEngine().getTime()+lifeSpan)); addChild(graphicalPart); - m_scene->updateShaders(); // TODO : optimisations needed } } diff --git a/src/scene/graphicalnode.cpp b/src/scene/graphicalnode.cpp index 0902be1..a8f8960 100644 --- a/src/scene/graphicalnode.cpp +++ b/src/scene/graphicalnode.cpp @@ -3,7 +3,8 @@ #include "glm/ext.hpp" #include -void GraphicalNode::setSceneTree(SceneTree *tree){ +void GraphicalNode::setSceneTree(SceneTree *tree) +{ if(isVisible()) { if(m_scene != nullptr) @@ -14,7 +15,8 @@ void GraphicalNode::setSceneTree(SceneTree *tree){ m_scene = tree; } -void GraphicalNode::resetTransform(){ +void GraphicalNode::resetTransform() +{ setTransform(glm::mat4()); } diff --git a/src/scene/gui/buttonnode.cpp b/src/scene/gui/buttonnode.cpp index ca7d0f8..fc62010 100644 --- a/src/scene/gui/buttonnode.cpp +++ b/src/scene/gui/buttonnode.cpp @@ -43,7 +43,6 @@ void ButtonNode::update() if(m_label->wasUpdated()){ m_label->setPosition(m_shape->getDimension()/glm::vec2(2,2) - m_label->getDimension()/glm::vec2(2,2)); - getEngine().getScene()->updateShaders(); } for (auto action : input->getActions()) diff --git a/src/scene/lightnode.cpp b/src/scene/lightnode.cpp index d8748f7..c198a64 100644 --- a/src/scene/lightnode.cpp +++ b/src/scene/lightnode.cpp @@ -3,6 +3,13 @@ #include #include +void LightNode::setSceneTree(SceneTree *tree) +{ + GraphicalNode::setSceneTree(tree); + if(m_scene != nullptr) + m_scene->registerLightType(m_light->getFlags()); +} + void LightNode::update() { if(m_transformChanged) diff --git a/src/scene/lightnode.h b/src/scene/lightnode.h index 8cb11a1..49d343a 100644 --- a/src/scene/lightnode.h +++ b/src/scene/lightnode.h @@ -11,6 +11,8 @@ class LightNode : public GraphicalNode public: LightNode(Light* light) : m_light(light) {} + virtual void setSceneTree(SceneTree* tree); + virtual void update(); virtual Light* getLight() { return m_light; } diff --git a/src/scene/meshnode.cpp b/src/scene/meshnode.cpp index 72b8c92..d0dca2a 100644 --- a/src/scene/meshnode.cpp +++ b/src/scene/meshnode.cpp @@ -6,6 +6,13 @@ #include #include +void MeshNode::setSceneTree(SceneTree *tree) +{ + GraphicalNode::setSceneTree(tree); + if(m_scene != nullptr) + m_scene->registerMeshType(m_geometry.mesh->getFlags()); +} + void MeshNode::setDepth(float depth){ m_geometry.mesh->setDepth(depth); } diff --git a/src/scene/meshnode.h b/src/scene/meshnode.h index a214855..e1aeae6 100644 --- a/src/scene/meshnode.h +++ b/src/scene/meshnode.h @@ -26,6 +26,8 @@ public: // this behaviour allows the use of the same meshes in multiple nodes MeshNode(Mesh* mesh, bool visible = true) : GraphicalNode(visible), m_geometry(mesh, glm::mat4()), m_rigidBody(nullptr) {} + virtual void setSceneTree(SceneTree* tree); + virtual void update(); void setDepth(float depth); diff --git a/src/scene/scenetree.cpp b/src/scene/scenetree.cpp index e3df85c..6a6fc08 100644 --- a/src/scene/scenetree.cpp +++ b/src/scene/scenetree.cpp @@ -13,7 +13,8 @@ SceneTree::SceneTree(const Engine &engine) : Scene(), m_engine(engine), - m_skybox(NULL) + m_shaderRefreshRequired(false), + m_camera(nullptr) { DeferredPipeline *pipeline = new DeferredPipeline(); m_pipeline = pipeline; @@ -28,9 +29,10 @@ SceneTree::~SceneTree() void SceneTree::setMainCamera(CameraNode *camNode) { - ((DeferredPipeline*)m_pipeline)->setCamera(camNode->getCamera()); + m_camera = camNode->getCamera(); + ((DeferredPipeline*)m_pipeline)->setCamera(m_camera); sf::Vector2u size = getEngine().getWindow()->getSize(); - camNode->getCamera()->resize(size.x, size.y); + m_camera->resize(size.x, size.y); } SceneIterator* SceneTree::getLights() @@ -43,11 +45,37 @@ SceneIterator* SceneTree::getGeometry() return new ArrayIterator(m_geometries); } +void SceneTree::getMeshTypes(std::vector &meshTypes) +{ + for(unsigned int type : m_meshTypes) + meshTypes.push_back(type); +} + +void SceneTree::getLightTypes(std::vector &lightTypes) +{ + for(unsigned int type : m_lightTypes) + lightTypes.push_back(type); +} + void SceneTree::update() { m_root.update(); } +void SceneTree::registerMeshType(unsigned int meshType) +{ + auto ret = m_meshTypes.emplace(meshType); + if(ret.second) + m_shaderRefreshRequired = true; +} + +void SceneTree::registerLightType(unsigned int lightType) +{ + auto ret = m_lightTypes.emplace(lightType); + if(ret.second) + m_shaderRefreshRequired = true; +} + void SceneTree::addToIndex(SceneNode* node){ Light *light = node->getLight(); GeometryNode *geometrynode = node->getGeometryNode(); @@ -80,5 +108,9 @@ void SceneTree::removeFromIndex(SceneNode *node){ void SceneTree::updateShaders() { - ((DeferredPipeline*) m_pipeline)->refreshScene(this); + if(m_shaderRefreshRequired) + { + ((DeferredPipeline*) m_pipeline)->refreshScene(this); + m_shaderRefreshRequired = false; + } } diff --git a/src/scene/scenetree.h b/src/scene/scenetree.h index eb23d51..dede801 100644 --- a/src/scene/scenetree.h +++ b/src/scene/scenetree.h @@ -3,6 +3,7 @@ #include #include +#include #include "SparrowRenderer/scene.h" #include "containernode.h" #include "engine.h" @@ -23,14 +24,17 @@ public: virtual SceneIterator* getLights(); virtual SceneIterator* getGeometry(); + virtual void getMeshTypes(std::vector &meshTypes); + virtual void getLightTypes(std::vector &lightTypes); + void update(); - Texture* getSkybox() {return m_skybox;} - void setSkybox(Texture* skybox) {m_skybox = skybox;} - void setMainCamera(CameraNode *camNode); + Camera* getCamera() const { return m_camera; } ContainerNode* getRootObject(){return &m_root;} + void registerMeshType(unsigned int meshType); + void registerLightType(unsigned int lightType); void addToIndex(SceneNode* node); void removeFromIndex(SceneNode *node); void updateShaders(); @@ -47,7 +51,10 @@ private: ContainerNode m_root; std::vector m_lights; std::vector m_geometries; - Texture* m_skybox; + std::unordered_set m_meshTypes; + std::unordered_set m_lightTypes; + bool m_shaderRefreshRequired; + Camera* m_camera; }; #endif // SCENETREE_H diff --git a/src/sparrowshell/sparrowshell.cpp b/src/sparrowshell/sparrowshell.cpp index 7f4477a..57970b9 100644 --- a/src/sparrowshell/sparrowshell.cpp +++ b/src/sparrowshell/sparrowshell.cpp @@ -147,7 +147,6 @@ void SparrowShell::toggleShell() // for(auto child : m_children) // child->toggleVisibility(); // m_buffer->toggleBuffer(); - m_scene->updateShaders(); } void SparrowShell::update() diff --git a/src/test/main.cpp b/src/test/main.cpp index 4020ad5..2b33b19 100644 --- a/src/test/main.cpp +++ b/src/test/main.cpp @@ -213,7 +213,6 @@ public: LightNode *sunLight = new LightNode(sun); scene->getRootObject()->addChild(ambientLight); - scene->getRootObject()->addChild(sunLight); if(m_config->scene == "sponza") { @@ -248,6 +247,7 @@ public: sun->setShadowView(glm::vec3(80)); } + scene->getRootObject()->addChild(sunLight); } std::string getScene(){return m_demo_scene;} @@ -427,7 +427,6 @@ int main(){ // engine.getScene()->getRootObject()->addChild(bgrn); // preparing shaders and launching the engine - engine.getScene()->updateShaders(); engine.start(); // pathfinding tests diff --git a/src/tools/scenepicker.cpp b/src/tools/scenepicker.cpp new file mode 100644 index 0000000..db0ec70 --- /dev/null +++ b/src/tools/scenepicker.cpp @@ -0,0 +1,90 @@ +#include "scenepicker.h" + +#include "engine.h" +#include "guitools.h" +#include "scene/scenetree.h" +#include "scene/playercharacternode.h" + +#include +#include +#include + +#include + +#include +#include +#include + +Mesh* ScenePicker::generateMesh() +{ + SphereGenerator generator; + PBRMaterial* mat = new PBRMaterial(); + mat->albedo = glm::vec3(1, 0, 0); // red + mat->emission = glm::vec3(0.3, 0, 0); // emits some red + mat->metallic = 0.6f; + mat->roughness = 0.3f; // quite shiny + Mesh* m = generator.generateGeodesicMesh(mat, 2, 0.3f); + m->computeNormals(); + m->setName("scenePicker"); + m->initGL(); + return m; +} + +ScenePicker::ScenePicker() : + MeshNode(generateMesh()), + m_pickSucceeded(false) +{ +} + +ScenePicker::~ScenePicker() +{ + delete m_geometry.mesh->getMaterial(); + delete m_geometry.mesh; +} + +void ScenePicker::update() +{ + pick(); + + bool isEnabled = true; + ImGui::Begin("Picker", &isEnabled); + if(m_pickSucceeded) + { + ImGui::Text("Intersection : ( %.3f, %.3f, %.3f )", m_pickedPos.x, m_pickedPos.y, m_pickedPos.z); + } + else + { + ImGui::Text("No intesection"); + } + // if(ImGui::Button("Teleport")) + //move player to target coordinate + ImGui::End(); + + if(!isEnabled) + getEngine().getGuiTools()->togglePicker(); +} + +void ScenePicker::pick() +{ + FirstPersonCamera* cam = dynamic_cast(getEngine().getScene()->getCamera()); + if(cam != nullptr) + { + glm::vec3 dir_cam = cam->getDirection()*100; + btVector3 start(cam->getEyePosition().x, cam->getEyePosition().y, cam->getEyePosition().z); + btVector3 end = start; + end += btVector3(start.x() + dir_cam.x, start.y() + dir_cam.y, start.z() + dir_cam.z); + btCollisionWorld::ClosestRayResultCallback RayCallback(start, end); + getEngine().getPhysics()->rayTest(start,end,RayCallback); + + m_pickSucceeded = RayCallback.hasHit(); + if(m_pickSucceeded) + { + btVector3 target = RayCallback.m_hitPointWorld; + m_pickedPos = glm::vec3(target.x(), target.y(), target.z()); + m_geometry.modelMatrix = glm::translate(glm::mat4(), m_pickedPos); + } + } + else + m_pickSucceeded = false; +} + diff --git a/src/tools/scenepicker.h b/src/tools/scenepicker.h new file mode 100644 index 0000000..41ab04d --- /dev/null +++ b/src/tools/scenepicker.h @@ -0,0 +1,26 @@ +#ifndef SCENEPICKER_H +#define SCENEPICKER_H + +#include "scene/meshnode.h" + +class ScenePicker : public MeshNode +{ + static Mesh* generateMesh(); + + glm::vec3 m_pickedPos; + bool m_pickSucceeded; + +public: + ScenePicker(); + + virtual ~ScenePicker(); + + virtual void update(); + + void pick(); + + glm::vec3 getIntersection() { return m_pickedPos; } + bool getTraceSucceeded() { m_pickSucceeded; } +}; + +#endif // SCENEPICKER_H