Cogs.Core
StaticModelSystem.cpp
1#include "StaticModelSystem.h"
2#include "Context.h"
3#include "EntityStore.h"
4
5#include "Resources/ModelManager.h"
6
7#include "Systems/Core/TransformSystem.h"
8#include "Systems/Core/MeshSystem.h"
9#include "Systems/Core/SceneSystem.h"
10#include "Systems/Core/RenderSystem.h"
11
12#include "Renderer/RenderList.h"
13
14#include "Foundation/Platform/Timer.h"
15
16namespace Cogs::Core
17{
19 {
20 StaticModelContext(Context * context, Memory::Allocator * allocator, SizeType size) :
21 transformSystem(allocator, size),
22 meshSystem(allocator, size),
23 sceneSystem(allocator, size),
24 renderSystem(allocator, size)
25 {
26 meshSystem.transformSystem = &transformSystem;
27 renderSystem.transformSystem = &transformSystem;
28
29 entityContext.transformSystem = &transformSystem;
30 entityContext.meshSystem = &meshSystem;
31 entityContext.renderSystem = &renderSystem;
32
33 transformSystem.initialize(context);
34 meshSystem.initialize(context);
35 sceneSystem.initialize(context);
36 renderSystem.initialize(context);
37 }
38
40
41 void update(Context * context)
42 {
43 if (batch.missing || dirty) {
44 transformSystem.update(context);
45 meshSystem.update(context);
46 sceneSystem.update(context);
47 renderSystem.update(context);
48
49 dirty = false;
50 }
51
52 meshSystem.postUpdate(context);
53 }
54
55 TransformSystem transformSystem;
56 MeshSystem meshSystem;
57 SceneSystem sceneSystem;
58 RenderSystem renderSystem;
59
60 RenderBatch batch;
61
62 ContextBase entityContext;
63
64 bool dirty = true;
65 };
66}
67
68Cogs::Core::StaticModelData::~StaticModelData()
69{
70
71}
72
73Cogs::Core::StaticModelSystem::~StaticModelSystem()
74{
75}
76
78{
79 for (auto & component : pool) {
80 auto & modelData = getData(&component);
81
82 auto model = HandleIsValid(component.model) ? context->modelManager->get(component.model) : nullptr;
83
84 if (component.hasChanged() || (model && model->isLoaded() && !modelData.isGeneration((uint8_t)model->getGeneration()))) {
85 if (model) {
86 const SizeType numParts = (SizeType)model->parts.size();
87
88 modelData.modelContext = std::make_shared<StaticModelContext>(context, context->memory->componentAllocator, numParts);
89
90 loadModel(context, component, modelData, model);
91 }
92 }
93
94 if (!modelData.modelContext) continue;
95
96 auto transformComponent = component.getComponent<TransformComponent>();
97
98 if (context->transformSystem->hasChanged(transformComponent)) {
99 modelData.modelContext->dirty = true;
100
101 for (auto & root : modelData.roots) {
102 auto rootTransform = root->getComponent<TransformComponent>();
103 rootTransform->position = transformComponent->position;
104 rootTransform->setChanged();
105 }
106 }
107
108 modelData.modelContext->update(context);
109 }
110}
111
112Cogs::Core::RenderSystem * Cogs::Core::StaticModelSystem::getRenderSystem(StaticModelComponent * modelComponent)
113{
114 auto & data = getData(modelComponent);
115
116 if (!data.modelContext) return nullptr;
117
118 return &data.modelContext->renderSystem;
119}
120
121Cogs::Core::MeshSystem * Cogs::Core::StaticModelSystem::getMeshSystem(StaticModelComponent * modelComponent)
122{
123 auto & data = getData(modelComponent);
124
125 if (!data.modelContext) return nullptr;
126
127 return &data.modelContext->meshSystem;
128}
129
130Cogs::Core::RenderBatch * Cogs::Core::StaticModelSystem::getRenderBatch(StaticModelComponent * modelComponent)
131{
132 auto & data = getData(modelComponent);
133
134 if (!data.modelContext) return nullptr;
135
136 return &data.modelContext->batch;
137}
138
139void Cogs::Core::StaticModelSystem::initializeCulling(CullingSource* cullingSource)
140{
141 for (auto & component : pool) {
142 auto & data = getData(&component);
143
144 if (!data.modelContext) continue;
145
146 data.modelContext->renderSystem.initializeCulling(cullingSource);
147 }
148}
149
150void Cogs::Core::StaticModelSystem::loadModel(Context * context, const StaticModelComponent & component, StaticModelData & modelData, Model * model)
151{
152 auto transformSystem = &modelData.modelContext->transformSystem;
153 auto meshSystem = &modelData.modelContext->meshSystem;
154 auto sceneSystem = &modelData.modelContext->sceneSystem;
155 auto renderSystem = &modelData.modelContext->renderSystem;
156
157 {
158 std::vector<EntityPtr> entities(model->parts.size());
159 std::vector<ComponentHandle> transformComponents(model->parts.size());
160 std::vector<ComponentHandle> sceneComponents(model->parts.size());
161
162 const auto groupId = hash("Group");
163 const auto meshPartId = hash("MeshPart");
164
165 auto store = context->store;
166
167 store->createEntities(model->parts.size(), entities, [transformSystem, meshSystem, sceneSystem, renderSystem](Entity* e) {
168 if (auto h = e->getComponentHandle<TransformComponent>(); h) {
169 transformSystem->destroyComponent(h);
170 }
171 if (auto h = e->getComponentHandle<SceneComponent>(); h) {
172 sceneSystem->destroyComponent(h);
173 }
174 if (auto h = e->getComponentHandle<MeshComponent>(); h) {
175 meshSystem->destroyComponent(h);
176 }
177 if (auto h = e->getComponentHandle<MeshRenderComponent>(); h) {
178 renderSystem->destroyComponent(h);
179 }
180 });
181
182 bool shareMaterial = true; // component.shareMaterial;
183 bool inheritMaterial = false;// component.inheritMaterial;
184
185 for (size_t i = 0; i < model->parts.size(); ++i) {
186 const auto & part = model->parts[i];
187 auto & entity = entities[i];
188
189 auto partName = model->getPartName(part);
190 if (!partName.empty()) {
191 entity->setName(partName);
192 }
193
194 auto transformComponent = transformSystem->createComponent();
195 transformComponents[i] = transformComponent;
196
197 entity->addComponent(transformComponent);
198
199 sceneComponents[i] = sceneSystem->createComponent();
200 entity->addComponent(sceneComponents[i]);
201
202 if (part.parentIndex != NoParentPart) {
203 sceneComponents[part.parentIndex].resolveComponent<SceneComponent>()->children.emplace_back(entity);
204 transformComponent.resolveComponent<TransformComponent>()->parent = transformComponents[part.parentIndex];
205 } else {
206 component.getComponent<SceneComponent>()->children.emplace_back(entity);
207 modelData.roots.emplace_back(entity.get());
208 }
209
210 EntityData* entityData = static_cast<EntityData *>(entity->getUserData());
211 entityData->templateId = (part.meshIndex != NoIndex ? meshPartId : groupId);
212 entityData->entityContext = &modelData.modelContext->entityContext;
213
214 if (part.meshIndex < model->meshes.size() && part.materialIndex < model->materials.size()) {
215 auto mesh = model->meshes[part.meshIndex];
216 auto material = model->materials[part.materialIndex];
217
218 auto mcHandle = meshSystem->createComponent();
219 entity->addComponent(mcHandle);
220
221 auto meshComponent = mcHandle.resolveComponent<MeshComponent>();
222 meshComponent->meshHandle = mesh;
223 meshComponent->setChanged();
224
225 auto mrcHandle = renderSystem->createComponent();
226 entity->addComponent(mrcHandle);
227
228 auto renderComponent = mrcHandle.resolveComponent<MeshRenderComponent>();
229 renderComponent->startIndex = part.startIndex;
230 renderComponent->vertexCount = part.vertexCount;
231
232 if (model->bounds.size() > i) {
233 renderSystem->setLocalBounds(renderComponent, model->bounds[i]);
234 }
235
236 if (!inheritMaterial && HandleIsValid(material)) {
237 if (shareMaterial) {
238 renderComponent->material = material;
239 }
240 }
241 }
242 }
243
244 for (size_t i = 0; i < model->parts.size(); ++i) {
245 const auto & part = model->parts[i];
246
247 transformSystem->setLocalTransform(transformComponents[i].resolveComponent<TransformComponent>(), model->getPartTransform(part));
248 }
249 }
250
251 modelData.setGeneration((uint8_t)model->getGeneration());
252}
ComponentType * getComponent() const
Definition: Component.h:159
Container for components, providing composition of dynamic entities.
Definition: Entity.h:18
ComponentHandle getComponentHandle() const
Get a component handle to the first component implementing the given type.
Definition: Entity.h:90
virtual void initialize(Context *context)
Initialize the system.
void update()
Updates the system state to that of the current frame.
void postUpdate(Context *) override
Context base contains the parts of a Context that may be instantiated by static scene or model instan...
Definition: Context.h:60
A Context instance contains all the services, systems and runtime components needed to use Cogs.
Definition: Context.h:83
std::unique_ptr< struct MemoryContext > memory
Memory and allocation info.
Definition: Context.h:171
void update(Context *context) override
Provided for custom update logic in derived systems.
Definition: MeshSystem.cpp:5
The mesh render system handles MeshRenderComponents.
Definition: RenderSystem.h:75
void initialize(Context *context) override
Initialize the system.
void update(Context *context) override
Provided for custom update logic in derived systems.
The scene system handles SceneComponent instances, managing hierarchical visibility and pickability b...
Definition: SceneSystem.h:24
void update(Context *context)
Updates the scene system.
Definition: SceneSystem.cpp:8
Defines a 4x4 transformation matrix for the entity and a global offset for root entities.
glm::vec3 position
Local position relative to the global coordinates, or the parent coordinate system if the parent fiel...
The transform system handles TransformComponent instances, calculating local and global transform dat...
void update(class Context *context) override
Updates the transform system.
Base allocator implementation.
Definition: Allocator.h:30
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....
bool HandleIsValid(const ResourceHandle_t< T > &handle)
Check if the given resource is valid, that is not equal to NoHandle or InvalidHandle.
constexpr size_t hash() noexcept
Simple getter function that returns the initial value for fnv1a hashing.
Definition: HashFunctions.h:62
ComponentIndex SizeType
Type used to track the size of pools.
Definition: Component.h:19