Skip to content

Commit

Permalink
#5893: Detect light entities automatically in addEntity/removeEntity
Browse files Browse the repository at this point in the history
  • Loading branch information
codereader committed Jan 27, 2022
1 parent 6822fcc commit c1996a6
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 0 deletions.
8 changes: 8 additions & 0 deletions include/irender.h
Expand Up @@ -671,6 +671,8 @@ class RenderSystem

/**
* Register the given entity to be considered during rendering.
* If this entity is a light it will be automatically recognised
* and inserted into the set of lights.
*/
virtual void addEntity(const IRenderEntityPtr& renderEntity) = 0;

Expand All @@ -686,6 +688,12 @@ class RenderSystem
*/
virtual void foreachEntity(const std::function<void(const IRenderEntityPtr&)>& functor) = 0;

/**
* Enumerates all known render lights in this system, invoking
* the functor for each of them
*/
virtual void foreachLight(const std::function<void(const RendererLightPtr&)>& functor) = 0;

/**
* \brief
* Main render method.
Expand Down
23 changes: 23 additions & 0 deletions radiantcore/rendersystem/OpenGLRenderSystem.cpp
Expand Up @@ -509,6 +509,15 @@ void OpenGLRenderSystem::addEntity(const IRenderEntityPtr& renderEntity)
{
throw std::logic_error("Duplicate entity registration.");
}

auto light = std::dynamic_pointer_cast<RendererLight>(renderEntity);

if (!light) return;

if (!_lights.insert(light).second)
{
throw std::logic_error("Duplicate light registration.");
}
}

void OpenGLRenderSystem::removeEntity(const IRenderEntityPtr& renderEntity)
Expand All @@ -517,13 +526,27 @@ void OpenGLRenderSystem::removeEntity(const IRenderEntityPtr& renderEntity)
{
throw std::logic_error("Entity has not been registered.");
}

auto light = std::dynamic_pointer_cast<RendererLight>(renderEntity);

if (!light) return;

if (_lights.erase(light) == 0)
{
throw std::logic_error("Light has not been registered.");
}
}

void OpenGLRenderSystem::foreachEntity(const std::function<void(const IRenderEntityPtr&)>& functor)
{
std::for_each(_entities.begin(), _entities.end(), functor);
}

void OpenGLRenderSystem::foreachLight(const std::function<void(const RendererLightPtr&)>& functor)
{
std::for_each(_lights.begin(), _lights.end(), functor);
}

// Define the static OpenGLRenderSystem module
module::StaticModule<OpenGLRenderSystem> openGLRenderSystemModule;

Expand Down
4 changes: 4 additions & 0 deletions radiantcore/rendersystem/OpenGLRenderSystem.h
Expand Up @@ -29,6 +29,9 @@ class OpenGLRenderSystem final
// The set of registered render entities
std::set<IRenderEntityPtr> _entities;

// The set of registered render lights
std::set<RendererLightPtr> _lights;

// whether this module has been realised
bool _realised;

Expand Down Expand Up @@ -97,6 +100,7 @@ class OpenGLRenderSystem final
void addEntity(const IRenderEntityPtr& renderEntity) override;
void removeEntity(const IRenderEntityPtr& renderEntity) override;
void foreachEntity(const std::function<void(const IRenderEntityPtr&)>& functor) override;
void foreachLight(const std::function<void(const RendererLightPtr&)>& functor) override;

/* OpenGLStateManager implementation */
void insertSortedState(const OpenGLStates::value_type& val) override;
Expand Down
37 changes: 37 additions & 0 deletions test/Renderer.cpp
Expand Up @@ -275,6 +275,18 @@ std::size_t getEntityCount(RenderSystemPtr& renderSystem)
return count;
}

std::size_t getLightCount(RenderSystemPtr& renderSystem)
{
std::size_t count = 0;

renderSystem->foreachLight([&](const RendererLightPtr&)
{
++count;
});

return count;
}

}

// Ensure that any entity in the scene is connected to the rendersystem
Expand Down Expand Up @@ -355,4 +367,29 @@ TEST_F(RenderSystemTest, EntityEnumeration)
EXPECT_EQ(visitedEntities.front(), entity) << "We should've hit our known entity";
}

TEST_F(RenderSystemTest, LightRegistration)
{
auto rootNode = GlobalMapModule().getRoot();
auto renderSystem = rootNode->getRenderSystem();

EXPECT_TRUE(renderSystem);
EXPECT_EQ(getEntityCount(renderSystem), 0) << "Rendersystem should be pristine";
EXPECT_EQ(getLightCount(renderSystem), 0) << "Rendersystem should be pristine";

auto light = createByClassName("atdm:light_base");
auto entity = createByClassName("func_static");

scene::addNodeToContainer(entity, rootNode);
EXPECT_EQ(getLightCount(renderSystem), 0) << "Rendersystem should still be empty";

scene::addNodeToContainer(light, rootNode);
EXPECT_EQ(getLightCount(renderSystem), 1) << "Rendersystem should contain one light now";

scene::removeNodeFromParent(entity);
EXPECT_EQ(getLightCount(renderSystem), 1) << "Rendersystem should still contain one light";

scene::removeNodeFromParent(light);
EXPECT_EQ(getLightCount(renderSystem), 0) << "Rendersystem should be empty now";
}

}

0 comments on commit c1996a6

Please sign in to comment.