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->transform.trs.position = transformComponent->transform.trs.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.
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
glm::vec3 position
Local position relative to the global coordinates, or the parent coordinate system if the parent fiel...