3#include "Utilities/Parsing.h"
6#include "CameraSystem.h"
7#include "TransformSystem.h"
8#include "Services/Variables.h"
10#include "Components/Core/TransformComponent.h"
11#include "Components/Core/SceneComponent.h"
12#include "Components/Core/RenderComponent.h"
13#include "Components/Core/MeshComponent.h"
14#include "Components/Core/SceneComponent.h"
15#include "Systems/Core/RenderSystem.h"
17#include "Foundation/ComponentModel/Entity.h"
18#include "Foundation/Logging/Logger.h"
27 float getMinDistanceToBBox(
Context* context,
Entity* entity,
const glm::vec3& refWorld)
29 auto minDistance = std::numeric_limits<float>::max();
31 for (
auto & child : sceneComp->children) {
32 minDistance = std::min(minDistance, getMinDistanceToBBox(context, child.get(), refWorld));
37 const auto & bbox = context->renderSystem->getWorldBounds(renderComp);
38 if (bbox.min.x <= bbox.max.x) {
39 auto p = glm::clamp(refWorld, bbox.min, bbox.max);
40 auto l = p - refWorld;
41 auto d2 = glm::dot(l, l);
42 if (d2 < minDistance*minDistance) {
43 minDistance = std::sqrt(d2);
57 void calculateLevelOfDetail(
Context * context,
60 const glm::vec3 & cameraCenter,
65 bool transformChanged = context->transformSystem->hasChanged(transform);
67 if (!transformChanged && !cameraChanged)
return;
69 switch (component.
policy) {
72 glm::vec3 center = glm::vec3(context->transformSystem->getLocalToWorld(transform) * glm::vec4(0, 0, 0, 1));
74 const float distance = glm::clamp(glm::length(center - cameraCenter), 0.0f, std::numeric_limits<float>::max());
78 for (
size_t i = 0; i < component.
thresholds.size(); ++i) {
79 if (distance > component.
thresholds[i]) index = i;
82 lodData.currentLodIndex =
static_cast<uint8_t
>(index);
87 glm::mat4 localToEye = cameraData.viewMatrix * context->transformSystem->getLocalToWorld(transform);
90 float lx2 = glm::dot(localToEye[0], localToEye[0]);
91 float ly2 = glm::dot(localToEye[1], localToEye[1]);
92 float lz2 = glm::dot(localToEye[2], localToEye[2]);
93 float r = glm::sqrt(glm::max(glm::max(lx2, ly2), lz2));
96 glm::vec4 ah = cameraData.projectionMatrix * localToEye[3];
97 glm::vec4 bh = cameraData.projectionMatrix * (localToEye[3] + glm::vec4(r, 0.f, 0.f, 0.f));
98 float w = 0.5f * cameraData.viewportSize.x * glm::distance((1.f / ah.w) * glm::vec2(ah.x, ah.y), (1.f / bh.w) * glm::vec2(bh.x, bh.y));
100 lodData.detailLevel = std::ceil(glm::pi<float>() / std::acos(1.f - component.
geometricTolerance / std::max(std::numeric_limits<float>::epsilon(), w)));
116 auto camera =
context->cameraSystem->getMainCamera();
118 const auto & cameraData =
context->cameraSystem->getData(camera);
119 const glm::mat4 & worldToClip = cameraData.viewProjection;
120 const glm::mat4 & clipToWorld = cameraData.inverseViewProjectionMatrix;
122 glm::vec3 cameraCenter = glm::vec3(
context->transformSystem->getLocalToWorld(cameraTransform) * glm::vec4(0, 0, 0, 1));
124 for (
const auto & component :
pool) {
125 auto & lodData = getData<LodData>(&component);
131 lodData.localToClip = worldToClip *
context->transformSystem->getLocalToWorld(transformComponent);
132 lodData.clipToLocal = glm::inverse(
context->transformSystem->getLocalToWorld(transformComponent)) * clipToWorld;
136 if (!sceneComponent)
continue;
138 calculateLevelOfDetail(
context, component, lodData, cameraCenter, cameraData,
true);
142 lodData.previousLodIndex = lodData.currentLodIndex;
144 const uint8_t numLevels =
static_cast<uint8_t
>(sceneComponent->children.size());
149 for (
size_t i = 0; i < sceneComponent->children.size(); i++) {
151 auto * childSceneComp = sceneComponent->children[i]->getComponent<
SceneComponent>();
152 childSceneComp->
visible = i == lodData.currentLodIndex;
153 childSceneComp->setChanged();
158 for (uint8_t i = 0; i < numLevels; ++i) {
159 auto & child = sceneComponent->children[i];
161 child->getComponents(renderComponents);
163 for (
auto & renderComponent : renderComponents) {
164 renderComponent.lod.selectedLod = lodData.currentLodIndex;
165 renderComponent.lod.currentLod = i;
166 renderComponent.lod.numLods = numLevels;
167 renderComponent.lod.lodFraction = 0;
170 const auto childSceneComponent = child->getComponent<
SceneComponent>();
174 for (
auto & child : component.children) {
175 child->getComponents(renderComponents);
177 for (
auto & renderComponent : renderComponents) {
178 renderComponent.lod.selectedLod = lodData.currentLodIndex;
179 renderComponent.lod.currentLod = i;
180 renderComponent.lod.numLods = numLevels;
181 renderComponent.lod.lodFraction = 0;
186 if (childSceneComponent) {
187 updateChildren(*childSceneComponent);
192 updateChildren(*childSceneComponent);
Typed collection of components.
ComponentType * getComponent() const
Container for components, providing composition of dynamic entities.
T * getComponent() const
Get a pointer to the first component implementing the given type in the entity.
Context * context
Pointer to the Context instance the system lives in.
void update()
Updates the system state to that of the current frame.
ComponentPool< ComponentType > pool
Pool of components managed by the system.
A Context instance contains all the services, systems and runtime components needed to use Cogs.
std::unique_ptr< class Variables > variables
Variables service instance.
Contains data describing level of detail behavior for the entity the component belongs to.
std::vector< float > thresholds
Threshold values to switch levels of detail at when the policy in use is distance based (for example ...
LodPolicy policy
The policy used for determining the level of detail for this entity.
float geometricTolerance
Geometric tolerance value applied when the lodPolicy field is set to LodPolicy::GeometricTolerance.
bool separateHierarchies
Enable old-style lod'ing with a completely separate hierarchy for each lod-level.
GeometricErrorKind geometricErrorKind
Specifies what kind of error measure that is preferred.
float previousFrameStickyness
A number in [0,1] that indicates resilience to change, used to minimize popping.
Renders the contents of a MeshComponent using the given materials.
Contains information on how the entity behaves in the scene.
bool visible
If the entity this component is a member of should be visible.
Log implementation class.
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....
@ GeometricTolerance
Use a geometric error bound to determine how refined geometry needs to be at its current position.
@ None
No policy applied, the LodSystem will take no action on the entity.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Contains all Cogs related functionality.
Contains data describing a Camera instance and its derived data structured such as matrix data and vi...
Defines level of detail data calculated by the LodSystem.