Cogs.Core
CubeMarkerSystem.cpp
1#include "CubeMarkerSystem.h"
2
3#include "Context.h"
4#include "EntityStore.h"
5
6#include "Resources/Mesh.h"
7#include "Resources/MeshManager.h"
8#include "Resources/MaterialManager.h"
9#include "Resources/DefaultMaterial.h"
10#include "Resources/VertexFormats.h"
11
12#include "Components/Appearance/MaterialComponent.h"
13#include "Components/Core/SubMeshRenderComponent.h"
14#include "Components/Core/TransformComponent.h"
15#include "Components/Core/MeshComponent.h"
16#include "../Components/AxisCubeComponent.h"
17#include "Components/Core/SceneComponent.h"
18
19#include "Systems/Core/TransformSystem.h"
20
21#include "Utilities/Math.h"
22
23namespace Cogs
24{
25 namespace Core
26 {
27 void CubeMarkerSystem::createWallMarkers(CubeMarkerData & cmapData, CubeMarkerComponent & cmapComp)
28 {
29 EntityPtr cube = cmapData.cube.lock();
30
31 if (cmapData.wallMarkerShapes[0].lock()) {
32 return; // we already have the entities, nothing to do.
33 }
34 if (!cube) {
35 return; // no cube into which to embed, nothing to do
36 }
37
38 auto axisCubeComp = cube->getComponent<AxisCubeComponent>();
39 auto cubeTransformComp = cube->getComponent<TransformComponent>();
40
41 if (!axisCubeComp || !cubeTransformComp) {
42 return; // not a suitable entity
43 }
44
45 ComponentHandle cubeTransformCompH = context->transformSystem->getHandle(cubeTransformComp);
46
47 for (int axis = 0; axis < 3; axis++) {
48 // Create entity
49 EntityPtr wallMarker = context->store->createChildEntity("SubMeshPart", cmapComp.getContainer());
50 cmapData.wallMarkerShapes[axis] = wallMarker;
51
52 // Add mesh
53 auto meshComp = wallMarker->getComponent<MeshComponent>();
54 meshComp->meshHandle = createWallMarkerMesh(context);
55
56 // Setup transform and transform relationship
57 auto transformComponent = wallMarker->getComponent<TransformComponent>();
58 glm::vec3 a(axis == 0 ? 1.f : 0.f, axis == 1 ? 1.f : 0.f, axis == 2 ? 1.f : 0.f);
59 transformComponent->rotation = Cogs::Core::getRotation(glm::vec3(0.f, 0.f, 1.f), a);
60 transformComponent->scale = glm::vec3(cmapComp.markerSize, cmapComp.markerSize, 1.f);
61 transformComponent->parent = cubeTransformCompH;
62 context->transformSystem->updateTransformData(*transformComponent);
63 }
64
65 updateWallMarkers(cmapData, cmapComp, true);
66 }
67
68 void CubeMarkerSystem::updateWallMarkers(CubeMarkerData& cubeMarkerData, CubeMarkerComponent& cubeMarkerComp, bool force)
69 {
70 // update colors
71 glm::vec4 colors[3] = { cubeMarkerComp.xColor, cubeMarkerComp.yColor, cubeMarkerComp.zColor };
72
73 // Update wall marker position and length
74 EntityPtr cube = cubeMarkerData.cube.lock();
75 if (cubeMarkerComp.showWallMarkers && cube) {
76 AxisCubeComponent* axisCubeComp = cube->getComponent<AxisCubeComponent>();
77 TransformComponent* cubeTransformComp = cube->getComponent<TransformComponent>();
78 TransformComponent* markerTransformComp = cubeMarkerComp.getComponent<TransformComponent>();
79 if (force || axisCubeComp->hasChanged() || cubeTransformComp->hasChanged() || markerTransformComp->hasChanged()) {
80 glm::vec4 ph =
81 axisCubeComp->worldToLocal *
82 context->transformSystem->getLocalToWorld(markerTransformComp)*glm::vec4(0.f, 0.f, 0.f, 1.f);
83
84 glm::vec3 p = (1.f / ph.w)*glm::vec3(ph.x, ph.y, ph.z);
85 for (int axis = 0; axis < 3; axis++) {
86 EntityPtr wallMarker = cubeMarkerData.wallMarkerShapes[axis].lock();
87 if (wallMarker) {
88 TransformComponent* wallMarkertransformComp = wallMarker->getComponent<TransformComponent>();
89 wallMarkertransformComp->position = p;
90 wallMarkertransformComp->scale = glm::vec3(cubeMarkerComp.markerSize,
91 cubeMarkerComp.markerSize,
92 glm::mix(axisCubeComp->adjustedMinCorner[axis],
93 axisCubeComp->adjustedMaxCorner[axis],
94 axisCubeComp->markerFaces[axis]) - p[axis]);
95 wallMarkertransformComp->setChanged();
96
97 uint32_t key = ((uint32_t(255.f*colors[axis].r) & 0xff) << 24)
98 | ((uint32_t(255.f*colors[axis].g) & 0xff) << 16)
99 | ((uint32_t(255.f*colors[axis].b) & 0xff) << 8)
100 | ((uint32_t(255.f*colors[axis].a) & 0xff));
101
102 if (force || (cubeMarkerData.colorKeys[axis] != key)) {
103 // update material
104
105 auto meshRenderComp = wallMarker->getComponent<SubMeshRenderComponent>();
106 auto it = wallMarkerMaterials.find(key);
107 auto jt = wallMarkerMaterials.find(cubeMarkerData.colorKeys[axis]); // Note, it is O.K if colorKey is uninitialized.
108 if (it != wallMarkerMaterials.end()) {
109 // We already have a matching material, lets use that one.
110 meshRenderComp->materials.resize(3);
111 meshRenderComp->materials[0] = it->second.solid;
112 meshRenderComp->materials[1] = it->second.line;
113 meshRenderComp->materials[2] = it->second.line;
114
115 // Check if anyone uses the handle to our old material, and if not, remove our ref to it (and let it be deleted).
116 if (jt != wallMarkerMaterials.end()) {
117 if (jt->second.solid.resolve()->referenceCount() == 1) {
118 wallMarkerMaterials.erase(jt);
119 }
120 }
121 }
122 else {
123 // No matching material, either make a new one or recycle the one we have.
124
125 WallMarkerMaterials materials;
126 if ((jt != wallMarkerMaterials.end()) && (jt->second.solid.resolve()->referenceCount() == 2)) {
127 // We have an existing material that is not in use by anyone else, we use that one.
128 materials = jt->second;
129 wallMarkerMaterials.erase(jt);
130 }
131 else {
132
133 // Either we didn't have a material beforehand, or the one was in use by additional parties.
134 materials.solid = context->materialInstanceManager->createMaterialInstance(context->materialManager->getDefaultMaterial());
135 materials.solid->setVariant("LightModel", "BaseColor");
136 materials.solid->setVariant("EnableLighting", false);
137 materials.solid->setBoolProperty(DefaultMaterial::EnableLighting, false);
138 materials.solid->options.depthBiasEnabled = true;
139 materials.solid->options.depthBias.constant = -1.f;
140 materials.solid->options.depthBias.slope = -1.f;
141 materials.solid->options.depthBias.clamp = 100.f;
142 materials.solid->options.cullMode = CullMode::None;
143
144 materials.line = context->materialInstanceManager->createMaterialInstance(context->materialManager->getDefaultMaterial());
145 materials.line->setPermutation("Line");
146 materials.line->setBoolProperty(DefaultMaterial::EnableLighting, false);
147 materials.line->options.depthBiasEnabled = true;
148 materials.line->options.depthBias.constant = -1.f;
149 materials.line->options.depthBias.slope = -1.f;
150 materials.line->options.depthBias.clamp = 100.f;
151 }
152
153 // Update refs and set colors
154 meshRenderComp->materials.resize(3);
155 meshRenderComp->materials[0] = materials.solid;
156 meshRenderComp->materials[1] = materials.line;
157 meshRenderComp->materials[2] = materials.line;
158 materials.solid->setVec4Property(DefaultMaterial::DiffuseColor, 0.5f*colors[axis]);
159 materials.line->setVec4Property(DefaultMaterial::DiffuseColor, colors[axis]);
160 wallMarkerMaterials[key] = materials;
161 }
162 cubeMarkerData.colorKeys[axis] = key;
163 meshRenderComp->setChanged();
164 }
165 }
166
167 }
168 }
169 }
170 }
171
172 void CubeMarkerSystem::destroyWallMarkers(CubeMarkerData& cmapData, CubeMarkerComponent& cmapComp)
173 {
174 for (int axis = 0; axis < 3; axis++) {
175 EntityPtr wallMarker = cmapData.wallMarkerShapes[axis].lock();
176 if (wallMarker) {
177 context->store->removeChild(cmapComp.getContainer(), wallMarker.get());
178 cmapData.wallMarkerShapes[axis].reset();
179 }
180 }
181 }
182
183 void CubeMarkerSystem::createCenterMarker(CubeMarkerData& cmapData, CubeMarkerComponent& cmapComp)
184 {
185 EntityPtr centerMarker = cmapData.centerMarkerShape.lock();
186 if (centerMarker) {
187 return; // Nothing to do
188 }
189 centerMarker = context->store->createChildEntity("Sphere", cmapComp.getContainer());
190 cmapData.centerMarkerShape = centerMarker;
191
192 auto * thisMatComp = cmapComp.getComponent<MaterialComponent>();
193 auto * thatMatComp = centerMarker->getComponent<MaterialComponent>();
194 thatMatComp->copyProperties(thisMatComp);
195 updateCenterMarker(cmapData, cmapComp, true);
196 }
197
198 void CubeMarkerSystem::updateCenterMarker(CubeMarkerData& cubeMarkerData, CubeMarkerComponent& cubeMarkerComp, bool force)
199 {
200 EntityPtr centerMarker = cubeMarkerData.centerMarkerShape.lock();
201 if (centerMarker) {
202 if (force || cubeMarkerComp.hasChanged()) {
203 TransformComponent* mtfComp = centerMarker->getComponent<TransformComponent>();
204 mtfComp->scale = glm::vec3(cubeMarkerComp.markerSize);
205 mtfComp->setChanged();
206 }
207 }
208 }
209
210 void CubeMarkerSystem::destroyCenterMarker(CubeMarkerData& cmapData, CubeMarkerComponent& cmapComp)
211 {
212 EntityPtr centerMarker = cmapData.centerMarkerShape.lock();
213 if (centerMarker) {
214 context->store->removeChild(cmapComp.getContainer(), centerMarker.get());
215 cmapData.centerMarkerShape.reset();
216 }
217 }
218
220 {
221 if (this->context != context) {
223 }
224
225 for (auto& cubeMarkerComp : pool) {
226
227 auto& cubeMarkerData = getData(&cubeMarkerComp);
228
229
230 auto * matComp = cubeMarkerComp.getComponent<MaterialComponent>();
231 if (matComp->hasChanged()) {
232 EntityPtr centerMarker = cubeMarkerData.centerMarkerShape.lock();
233 if (centerMarker) {
234 auto * thatMatComp = centerMarker->getComponent<MaterialComponent>();
235 thatMatComp->copyProperties(matComp);
236 }
237 }
238
239 // turn on and off stuff
240 if (cubeMarkerComp.hasChanged()) {
241 EntityPtr compCube = cubeMarkerComp.cube.lock();
242 EntityPtr dataCube = cubeMarkerData.cube.lock();
243
244 // cube embedding has changed, explicitly destroy wall markers
245 if (compCube != dataCube) {
246 destroyWallMarkers(cubeMarkerData, cubeMarkerComp);
247 cubeMarkerData.cube = cubeMarkerComp.cube;
248 }
249 if (cubeMarkerComp.showWallMarkers) {
250 createWallMarkers(cubeMarkerData, cubeMarkerComp);
251 }
252 else {
253 destroyWallMarkers(cubeMarkerData, cubeMarkerComp);
254 }
255
256 if (cubeMarkerComp.showCenterMarker) {
257 createCenterMarker(cubeMarkerData, cubeMarkerComp);
258 }
259 else {
260 destroyCenterMarker(cubeMarkerData, cubeMarkerComp);
261 }
262 }
263 updateCenterMarker(cubeMarkerData, cubeMarkerComp, false);
264 updateWallMarkers(cubeMarkerData, cubeMarkerComp, false);
265 }
266 }
267
268 MaterialInstanceHandle CubeMarkerSystem::createUnshadedMaterialInstance(Context * context, const glm::vec4 color)
269 {
270 MaterialInstanceHandle matH = context->materialInstanceManager->createMaterialInstance(context->materialManager->getDefaultMaterial());
271 MaterialInstance* matI = matH.resolve();
272 matI->setPermutation("Line");
273 matI->setBoolProperty(DefaultMaterial::EnableLighting, false);
274 matI->setVec4Property(DefaultMaterial::DiffuseColor, color);
275 matI->setVariant("LightModel", "BaseColor");
276 matI->setVariant("EnableLighting", false);
277 return matH;
278 }
279
280 MeshHandle CubeMarkerSystem::createWallMarkerMesh(Context * context)
281 {
282 static const int N = 20; // samples currently hard-coded.
283
284 std::vector<Cogs::Core::PositionVertex> V;
285 for (int i = 0; i < N; i++) {
286 float theta = float(i) * float((2.0 * glm::pi<double>()) / N);
287 float c = std::cos(theta);
288 float s = std::sin(theta);
289
290 V.push_back({ glm::vec3(c, s, 1.f) });
291 V.push_back({ glm::vec3(0.5f*c, 0.5f*s, 1.f) });
292 }
293 V.push_back({ glm::vec3(0.f, 0.f, 1.f) });
294 V.push_back({ glm::vec3(0.f, 0.f, 0.f) });
295
296 std::vector<unsigned int> tristrip;
297 for (int i = 0; i < N; i++) {
298 tristrip.push_back(2 * i + 0);
299 tristrip.push_back(2 * i + 1);
300 }
301 tristrip.push_back(0);
302 tristrip.push_back(1);
303
304 std::vector<unsigned int> linestrip;
305 for (int i = 0; i < N; i++) {
306 linestrip.push_back(2 * i);
307 }
308 linestrip.push_back(0);
309
310 std::vector<unsigned int> line;
311 line.push_back(2 * N);
312 line.push_back(2 * N+1);
313
314
315 MeshHandle M = context->meshManager->create();
316 Mesh* m = context->meshManager->get(M);
317 if (m) {
318 m->setVertexData(V.data(), V.size());
319
320 m->addSubMesh(std::span(tristrip), PrimitiveType::TriangleStrip);
321 m->addSubMesh(std::span(linestrip), PrimitiveType::LineStrip);
322 m->addSubMesh(std::span(line), PrimitiveType::LineList);
323 }
324
325 M->setBounds(Geometry::BoundingBox{ glm::vec3(-1, -1, -1), glm::vec3(1, 1, 1) });
326
327 return M;
328 }
329 } // namespace Core
330} // namespace Cogs
ComponentType * getComponent() const
Definition: Component.h:159
Context * context
Pointer to the Context instance the system lives in.
virtual void initialize(Context *context)
Initialize the system.
void update()
Updates the system state to that of the current frame.
ComponentPool< ComponentType > pool
Pool of components managed by the system.
ComponentHandle getHandle(const ComponentType *component)
Get a handle to the given Component instance.
A Context instance contains all the services, systems and runtime components needed to use Cogs.
Definition: Context.h:83
class EntityStore * store
Entity store.
Definition: Context.h:231
EntityPtr createChildEntity(const StringView &type, ComponentModel::Entity *parent, const StringView &name=StringView())
Create a new Entity, parenting it to the given parent.
void removeChild(ComponentModel::Entity *parent, const ComponentModel::Entity *entity)
Remove the parent-child relationship between parent and entity.
void updateTransformData(const TransformComponent &component)
Force an update of the transform data associated with the given component.
std::shared_ptr< ComponentModel::Entity > EntityPtr
Smart pointer for Entity access.
Definition: EntityPtr.h:12
@ None
No primitive culling performed.
Contains all Cogs related functionality.
Definition: FieldSetter.h:23
Handle to a Component instance.
Definition: Component.h:67
Exposes material properties for legacy entities and code.
Material instances represent a specialized Material combined with state for all its buffers and prope...
void setVec4Property(const VariableKey key, glm::vec4 value)
Set the vec4 property with the given key to value.
void setBoolProperty(const VariableKey key, bool value)
Set the bool property with the given key to value.
ResourceType * resolve() const
Resolve the handle, returning a pointer to the actual resource.
@ LineStrip
Line strip.
Definition: Common.h:122
@ LineList
List of lines.
Definition: Common.h:120
@ TriangleStrip
Triangle strip.
Definition: Common.h:118