Cogs.Core
BoundsInspector.cpp
1#include "imgui.h"
2
3#include "Inspectors.h"
4
5#include "InspectorGuiHelper.h"
6#include "Context.h"
7#include "Foundation/Logging/Logger.h"
8#include "Scene/GetBounds.h"
9#include "Utilities/Simplex.h"
10
11#include "Systems/Core/LightSystem.h"
12#include "Systems/Core/TransformSystem.h"
13#include "Systems/Core/RenderSystem.h"
14#include "Systems/Core/SubMeshRenderSystem.h"
15#include "Systems/Core/SpriteRenderSystem.h"
16
17using glm::mat4;
18using glm::vec4;
19using namespace Cogs::Geometry;
20using namespace Cogs::Core;
21
22namespace
23{
24 Cogs::Logging::Log logger = Cogs::Logging::getLogger("BoundsInspector");
25 void updateCameraDepthBounds(Cogs::Core::Context* context,
26 uint8_t* simplexScratch,
27 float& viewNear,
28 float& viewFar,
29 const BoundingBox& bbox,
30 const mat4& bboxViewMatrix,
31 const mat4& bboxViewMatrixInverse,
32 const mat4& bboxViewProjectionMatrix)
33 {
34 // Classify bounding box w.r.t. frustum
35 float localNear = std::numeric_limits<float>::max();
36 float localFar = -std::numeric_limits<float>::max();
37
38 int insideMask = 0;
39 int outsideMask = 0;
40 for (int i = 0; i < 8; i++) {
41 vec4 t(i & 1 ? bbox.min.x : bbox.max.x,
42 i & 2 ? bbox.min.y : bbox.max.y,
43 i & 4 ? bbox.min.z : bbox.max.z,
44 1.f);
45
46 vec4 c = bboxViewProjectionMatrix * t;
47 int pointMask = 0;
48 if (-c.w <= c.x) pointMask |= 0x1;
49 if (c.x <= c.w) pointMask |= 0x2;
50 if (-c.w <= c.y) pointMask |= 0x4;
51 if (c.y <= c.w) pointMask |= 0x8;
52 if (pointMask == 0xf) {
53 vec4 v = bboxViewMatrix*t;
54 float z = v.z / v.w;
55 assert(std::isfinite(z));
56 localNear = std::min(localNear, -z);
57 localFar = std::max(localFar, -z);
58 }
59 insideMask |= pointMask;
60 outsideMask |= ~pointMask & 0xf;
61 }
62
63 if (insideMask != 0xf) {
64 // All points was completely outside at least one clip-plane.
65 } else if (outsideMask == 0x0) {
66 // If insideMask == 0xf and outsideMask == 0x0, all points we're completely inside.
67
68 viewNear = std::min(viewNear, localNear);
69 viewFar = std::max(viewFar, localFar);
70 } else {
71 // If insideMask == 0xf and outsideMask != 0x0, at least one clip plane was pierced, resort to simplex algorithm
72
73 glm::mat4 bboxMinAlignedViewProjectionMatrix = glm::translate(bboxViewProjectionMatrix, bbox.min);
74 glm::mat4 bboxMinAlignedViewMatrix = glm::translate(bboxViewMatrix, bbox.min);
75
76 glm::vec3 e = bbox.max - bbox.min;
77 float scale = std::max(std::max(e.x, e.y), e.z);
78 if (scale <= 0.f) {
79 // 2016-04-12: chrisdy: TODO Handle single point properly.
80 return;
81 }
82
83 float epsilon = std::numeric_limits<float>::epsilon()*scale;
84
85 mat4 rows = glm::transpose(bboxMinAlignedViewProjectionMatrix);
86 glm::vec4 l = rows[3] + rows[0];
87 glm::vec4 r = rows[3] - rows[0];
88 glm::vec4 b = rows[3] + rows[1];
89 glm::vec4 t = rows[3] - rows[1];
90
91 double restrictions[7 * 4] =
92 {
93 1.0, 0.0, 0.0, std::max(epsilon, e.x), // x <= xmax-xmin
94 0.0, 1.0, 0.0, std::max(epsilon, e.y), // y <= ymax-ymin
95 0.0, 0.0, 1.0, std::max(epsilon, e.z), // z <= zmax-zmin
96 -l.x, -l.y, -l.z, l.w,
97 -r.x, -r.y, -r.z, r.w,
98 -b.x, -b.y, -b.z, b.w,
99 -t.x, -t.y, -t.z, t.w,
100 };
101
102 double objectives[2 * 3] = {
103 bboxViewMatrixInverse[2].x, bboxViewMatrixInverse[2].y, bboxViewMatrixInverse[2].z,
104 -bboxViewMatrixInverse[2].x, -bboxViewMatrixInverse[2].y, -bboxViewMatrixInverse[2].z,
105 };
106
107 double solutions[2 * 3];
108
109 auto rv = simplexMaximize(context,
110 (uintptr_t)simplexScratch,
111 solutions, 3,
112 objectives, 2,
113 restrictions, 7,
114 150);
115 if (rv == SimplexResult::NoFeasibleSolutions) {
116 // No intersection
117 } else if (rv == SimplexResult::OptimalSolutionFound) {
118 for (int i = 0; i < 2; i++) {
119 vec4 v = bboxMinAlignedViewMatrix*glm::vec4(solutions[3 * i + 0],
120 solutions[3 * i + 1],
121 solutions[3 * i + 2],
122 1.f);
123 float z = v.z / v.w;
124 assert(std::isfinite(z));
125 viewNear = std::min(viewNear, -z);
126 viewFar = std::max(viewFar, -z);
127 }
128 } else {
129 LOG_DEBUG(logger, "Simplex optimization failed (=%d), reverting to standard approach.", (int)rv);
130 for (int i = 0; i < 8; i++) {
131 vec4 tt(i & 1 ? bbox.min.x : bbox.max.x,
132 i & 2 ? bbox.min.y : bbox.max.y,
133 i & 4 ? bbox.min.z : bbox.max.z,
134 1.f);
135 vec4 v = bboxViewMatrix*tt;
136 float z = v.z / v.w;
137 assert(std::isfinite(z));
138 viewNear = std::min(viewNear, -z);
139 viewFar = std::max(viewFar, -z);
140 }
141
142 }
143 }
144 }
145}// namespace ...
146
147void Cogs::Core::boundsInspector(Context * context, bool * show)
148{
149 if (*show == false) return;
150 guiBegin("Bounds", show);
151 auto mainCamComp = context->cameraSystem->getMainCamera();
152
153 glm::vec3 origin = context->transformSystem->getOrigin();
154
155 if (ImGui::InputFloat3("Origin", &origin.x, "%.2f")) {
156 context->transformSystem->setOrigin(origin);
157 }
158
159 // Cameras Inspector
160 if(ImGui::CollapsingHeader("Cameras", ImGuiTreeNodeFlags_DefaultOpen)){
161 for (auto & camComp :context->cameraSystem->pool) {
162 RenderLayers layerMask = camComp.layerMask & ~RenderLayers::Sky;
163 auto * camEntity = camComp.getContainer();
164 auto & camData = context->cameraSystem->getData(&camComp);
165 auto name = camEntity->getName() + " (" + std::to_string(camEntity->getId()) + ")";
166 if (mainCamComp == &camComp)
167 name += " (Main Camera)";
168
169 float nearDist = std::numeric_limits<float>::max();
170 float farDist = -std::numeric_limits<float>::max();
171 context->bounds->getClipPlanes(context, nearDist, farDist, camComp, camData.viewMatrix);
172 float depthBoundNear = std::numeric_limits<float>::max();
173 float depthBoundFar = -std::numeric_limits<float>::max();
174 context->bounds->getCameraDepthBounds(context, depthBoundNear, depthBoundFar, camComp);
175
176 if (ImGui::TreeNode(getUniqueHeader(name).c_str())) {
177 {
178 ImGui::TreePush("CamerasColumnsTree");
179 ImGui::Columns(3, "BoundsColumns", true);
180
181 ImGui::Text("");
182 ImGui::NextColumn();
183 ImGui::Text("Near");
184 ImGui::NextColumn();
185 ImGui::Text("Far");
186 ImGui::Separator();
187 ImGui::NextColumn();
188
189 ImGui::Text("CameraData");
190 ImGui::NextColumn();
191 ImGui::Text("%f", camData.nearDistance);
192 ImGui::NextColumn();
193 ImGui::Text("%f", camData.farDistance);
194 ImGui::NextColumn();
195
196 ImGui::Text("getClipPlanes");
197 ImGui::NextColumn();
198 ImGui::Text("%f", nearDist);
199 ImGui::NextColumn();
200 ImGui::Text("%f", farDist);
201 ImGui::NextColumn();
202
203 ImGui::Text("getCameraDepthBounds");
204 ImGui::NextColumn();
205 ImGui::Text("%f", depthBoundNear);
206 ImGui::NextColumn();
207 ImGui::Text("%f", depthBoundFar);
208 ImGui::NextColumn();
209
210 ImGui::Columns(1);
211 ImGui::TreePop();
212 }
213 if(ImGui::TreeNode("RenderComponents")){
214 auto system = context->renderSystem;
215 ImGui::Columns(3, "BoundsColumns", true);
216 for (auto & comp : system->pool) {
217 if (!comp.isVisibleInLayer(layerMask)) continue;
218 if (comp.lod.currentLod != comp.lod.selectedLod) continue;
219
220 const BoundingBox& bb = system->getWorldBounds(&comp);
221 if (isEmpty(bb)) continue;
222 const mat4* bboxViewMatrix = &camData.viewMatrix;
223 const mat4* bboxViewMatrixInverse = &camData.inverseViewMatrix;
224 const mat4* bboxViewProjectionMatrix = &camData.viewProjection;
225
226 float n = std::numeric_limits<float>::max();
227 float f = -std::numeric_limits<float>::max();
228 float nearPlaneLimit = camComp.nearPlaneLimit;
229 std::vector<uint8_t> simplexScratch(simplexScratchSize(3, 2, 7));
230 ::updateCameraDepthBounds(context,
231 simplexScratch.data(),
232 n, f,
233 bb, *bboxViewMatrix, *bboxViewMatrixInverse, *bboxViewProjectionMatrix);
234 n = std::max(nearPlaneLimit, n);
235
236 auto * entity = comp.getContainer();
237 ImGui::Text("[%zu] %s", entity->getId(), entity->getName().c_str());
238 ImGui::NextColumn();
239 if(n == std::numeric_limits<float>::max()) ImGui::Text("max");
240 else ImGui::Text("%.2f", n);
241 ImGui::NextColumn();
242 if(f == -std::numeric_limits<float>::max()) ImGui::Text("-max");
243 else ImGui::Text("%.2f", f);
244 ImGui::NextColumn();
245 }
246 ImGui::Columns(1);
247 ImGui::TreePop();
248 }
249 if(ImGui::TreeNode("SubMesh")){
250 auto system = context->subMeshRenderSystem;
251 ImGui::Columns(3, "SubMeshBoundsColumns", true);
252 for (auto & comp : system->pool) {
253 if (!comp.isVisibleInLayer(layerMask)) continue;
254 if (comp.lod.currentLod != comp.lod.selectedLod) continue;
255
256 const BoundingBox& bb = system->getWorldBounds(&comp);
257 if (isEmpty(bb)) continue;
258 const mat4* bboxViewMatrix = &camData.viewMatrix;
259 const mat4* bboxViewMatrixInverse = &camData.inverseViewMatrix;
260 const mat4* bboxViewProjectionMatrix = &camData.viewProjection;
261
262 float n = std::numeric_limits<float>::max();
263 float f = -std::numeric_limits<float>::max();
264 float nearPlaneLimit = camComp.nearPlaneLimit;
265 std::vector<uint8_t> simplexScratch(simplexScratchSize(3, 2, 7));
266 ::updateCameraDepthBounds(context,
267 simplexScratch.data(),
268 n, f,
269 bb, *bboxViewMatrix, *bboxViewMatrixInverse, *bboxViewProjectionMatrix);
270 n = std::max(nearPlaneLimit, n);
271
272 auto * entity = comp.getContainer();
273 ImGui::Text("[%zu] %s", entity->getId(), entity->getName().c_str());
274 ImGui::NextColumn();
275 if(n == std::numeric_limits<float>::max()) ImGui::Text("max");
276 else ImGui::Text("%.2f", n);
277 ImGui::NextColumn();
278 if(f == -std::numeric_limits<float>::max()) ImGui::Text("-max");
279 else ImGui::Text("%.2f", f);
280 ImGui::NextColumn();
281 }
282 ImGui::Columns(1);
283 ImGui::TreePop();
284 }
285 if(ImGui::TreeNode("Sprite")){
286 auto system = context->spriteRenderSystem;
287 ImGui::Columns(3, "SpriteBoundsColumns", true);
288 for (auto & sprite : system->pool) {
289 if (!sprite.isVisibleInLayer(layerMask)) continue;
290 auto & data = system->getData(&sprite);
291 if (data.batchIndex == NoBatchIndex) continue;
292 const auto & batch = system->getSpriteBatch(data.batchIndex);
293
294 glm::vec4 p;
295 if (batch->positionMode == PositionMode::World) {
296 p = camData.viewMatrix * glm::vec4(data.position, 1);
297 } else if(batch->positionMode == PositionMode::Local){
298 p = camData.viewMatrix * batch->transform * glm::vec4(data.position, 1);
299 } else {
300 continue;
301 }
302
303 glm::vec4 c = camData.projectionMatrix * p;
304 int pointMask = 0;
305 if (-c.w <= c.x) pointMask |= 0x1;
306 if (c.x <= c.w) pointMask |= 0x2;
307 if (-c.w <= c.y) pointMask |= 0x4;
308 if (c.y <= c.w) pointMask |= 0x8;
309 int outsideMask = ~pointMask & 0xf;
310 if(outsideMask)
311 continue;
312
313 float n = (-p.z) * (1.f - std::numeric_limits<float>::epsilon());
314 float f = (-p.z) * (1.f + std::numeric_limits<float>::epsilon());
315 auto * entity = sprite.getContainer();
316 ImGui::Text("[%zu] %s", entity->getId(), entity->getName().c_str());
317 ImGui::NextColumn();
318 if(n == std::numeric_limits<float>::max()) ImGui::Text("max");
319 else ImGui::Text("%.2f", n);
320 ImGui::NextColumn();
321 if(f == -std::numeric_limits<float>::max()) ImGui::Text("-max");
322 else ImGui::Text("%.2f", f);
323 ImGui::NextColumn();
324 }
325 ImGui::Columns(1);
326 ImGui::TreePop();
327 }
328 if(ImGui::TreeNode("Extension")){
329 ImGui::Columns(3, "ExtensionBoundsColumns", true);
330 for (auto & bounds : context->bounds->getExtensions()) {
331 float nearPlaneLimit = std::numeric_limits<float>::quiet_NaN();
332 BoundingBox extensionBounds;
333 bounds->getBounds(context, extensionBounds, nearPlaneLimit);
334 float n = std::numeric_limits<float>::max();
335 float f = -std::numeric_limits<float>::max();
336 if (!isEmpty(extensionBounds)) {
337 float nb = depthBoundNear;
338 std::vector<uint8_t> simplexScratch(simplexScratchSize(3, 2, 7));
339 ::updateCameraDepthBounds(context,
340 simplexScratch.data(),
341 nb, f,
342 extensionBounds, camData.viewMatrix, camData.inverseViewMatrix, camData.viewProjection);
343 if (!std::isfinite(nearPlaneLimit)) nearPlaneLimit = camComp.nearPlaneLimit;
344 n = std::min(n, std::max(nearPlaneLimit, nb));
345 }
346 ImGui::Text("[-1] extension");
347 ImGui::NextColumn();
348 if(n == std::numeric_limits<float>::max()) ImGui::Text("max");
349 else ImGui::Text("%.2f", n);
350 ImGui::NextColumn();
351 if(f == -std::numeric_limits<float>::max()) ImGui::Text("-max");
352 else ImGui::Text("%.2f", f);
353 ImGui::NextColumn();
354 }
355 ImGui::Columns(1);
356 ImGui::TreePop();
357 }
358 ImGui::TreePop();
359 }
360 }
361 }
362
363 // Shadows Inspector
364 if(ImGui::CollapsingHeader("Shadows", ImGuiTreeNodeFlags_DefaultOpen)){
365 BoundingBox bb = context->bounds->getShadowBounds(context);
366 ImGui::TreePush("ShadowBoundsColumnsTree");
367 ImGui::Columns(3, "ShadowBoundsColumns", true);
368 ImGui::Text("");
369 ImGui::NextColumn();
370 ImGui::Text("Min");
371 ImGui::NextColumn();
372 ImGui::Text("Max");
373 ImGui::Separator();
374 ImGui::NextColumn();
375 ImGui::Text("ShadowBounds");
376 ImGui::NextColumn();
377 ImGui::Text("%.2f, %.2f, %.2f", bb.min.x, bb.min.y, bb.min.z);
378 ImGui::NextColumn();
379 ImGui::Text("%.2f, %.2f, %.2f", bb.max.x, bb.max.y, bb.max.z);
380 ImGui::NextColumn();
381 ImGui::Text("");
382 ImGui::NextColumn();
383 ImGui::Text("Near");
384 ImGui::NextColumn();
385 ImGui::Text("Far");
386 ImGui::Separator();
387 ImGui::Columns(1);
388 ImGui::TreePop();
389 for (auto & lightComp : context->lightSystem->pool) {
390 auto * entity = lightComp.getContainer();
391 auto name = entity->getName() + " (" + std::to_string(entity->getId()) + ")";
392
393 if (lightComp.enabled == false) {
394 name += " (disabled)";
395 }
396 else if (lightComp.castShadows == false) {
397 name += " (casts no shadows)";
398 }
399 if (ImGui::TreeNode(getUniqueHeader(name).c_str())) {
400 auto & lightData = context->lightSystem->getData(&lightComp);
401 ImGui::Columns(3, "ShadowBoundsColumns", true);
402 ImGui::Text("Near/FarDistance");
403 ImGui::NextColumn();
404 ImGui::Text("%f", lightData.nearDepths[0]);
405 ImGui::NextColumn();
406 ImGui::Text("%f", lightData.farDepths[std::max(0, lightData.numViewports-1)]);
407 ImGui::NextColumn();
408 ImGui::Columns(1);
409 ImGui::TreePop();
410 }
411 }
412 }
413
414 // Entities Inspector
415 if(ImGui::CollapsingHeader("Entities", ImGuiTreeNodeFlags_DefaultOpen)){
416 RenderLayers layerMask = RenderLayers::AllStandard;
417 {
418 BoundingBox bb;
419 context->bounds->getSceneBounds(context, bb.data(), RenderLayers::AllStandard);
420 ImGui::TreePush("SceneBoundsColumnsTree");
421 ImGui::Columns(4, "SceneBoundsColumns", true);
422 ImGui::Text("Entity");
423 ImGui::NextColumn();
424 ImGui::Text("Min");
425 ImGui::NextColumn();
426 ImGui::Text("Max");
427 ImGui::NextColumn();
428 ImGui::Text("Size");
429 ImGui::Separator();
430 ImGui::NextColumn();
431 ImGui::Text("SceneBounds");
432 ImGui::NextColumn();
433 ImGui::Text("%.2f, %.2f, %.2f", bb.min.x, bb.min.y, bb.min.z);
434 ImGui::NextColumn();
435 ImGui::Text("%.2f, %.2f, %.2f", bb.max.x, bb.max.y, bb.max.z);
436 ImGui::NextColumn();
437 glm::vec3 size = bb.max-bb.min;
438 ImGui::Text("%.2f, %.2f, %.2f", size.x, size.y, size.z);
439 ImGui::Columns(1);
440 ImGui::TreePop();
441 }
442 if(ImGui::TreeNode("RenderComponents")){
443 ImGui::Columns(4, "RenderComponentsBoundsColumns", true);
444 for (auto & comp : context->renderSystem->pool) {
445 if (!comp.isVisibleInLayer(layerMask)) continue;
446 const BoundingBox& bb = context->renderSystem->getWorldBounds(&comp);
447 auto * entity = comp.getContainer();
448 ImGui::Text("[%zu] %s", entity->getId(), entity->getName().c_str());
449 ImGui::NextColumn();
450 if(bb.min.x > bb.max.x){
451 ImGui::Text("max, max, max");
452 ImGui::NextColumn();
453 ImGui::Text("-max, -max, -max");
454 ImGui::NextColumn();
455 ImGui::Text("0, 0, 0");
456 }
457 else{
458 ImGui::Text("%.2f, %.2f, %.2f", bb.min.x, bb.min.y, bb.min.z);
459 ImGui::NextColumn();
460 ImGui::Text("%.2f, %.2f, %.2f", bb.max.x, bb.max.y, bb.max.z);
461 ImGui::NextColumn();
462 glm::vec3 size = bb.max-bb.min;
463 ImGui::Text("%.2f, %.2f, %.2f", size.x, size.y, size.z);
464 }
465 ImGui::NextColumn();
466 }
467 ImGui::Columns(1);
468 ImGui::TreePop();
469 }
470 if(ImGui::TreeNode("SubMesh")){
471 ImGui::Columns(4, "SubMeshBoundsColumns", true);
472 for (auto & comp : context->subMeshRenderSystem->pool) {
473 if (!comp.isVisibleInLayer(layerMask)) continue;
474 const Geometry::BoundingBox& bb = context->subMeshRenderSystem->getWorldBounds(&comp);
475 auto * entity = comp.getContainer();
476 ImGui::Text("[%zu] %s", entity->getId(), entity->getName().c_str());
477 ImGui::NextColumn();
478 if(bb.min.x > bb.max.x){
479 ImGui::Text("max, max, max");
480 ImGui::NextColumn();
481 ImGui::Text("-max, -max, -max");
482 ImGui::NextColumn();
483 ImGui::Text("0, 0, 0");
484 }
485 else{
486 ImGui::Text("%.2f, %.2f, %.2f", bb.min.x, bb.min.y, bb.min.z);
487 ImGui::NextColumn();
488 ImGui::Text("%.2f, %.2f, %.2f", bb.max.x, bb.max.y, bb.max.z);
489 ImGui::NextColumn();
490 glm::vec3 size = bb.max-bb.min;
491 ImGui::Text("%.2f, %.2f, %.2f", size.x, size.y, size.z);
492 }
493 ImGui::NextColumn();
494 }
495 ImGui::Columns(1);
496 ImGui::TreePop();
497 }
498 if(ImGui::TreeNode("Sprites")){
499 ImGui::Columns(4, "Sprites", true);
500 for (auto & comp : context->spriteRenderSystem->pool) {
501 if (!comp.isVisible()) continue;
502 if (!comp.isVisibleInLayer(layerMask)) continue;
503 BoundingBox bb = context->spriteRenderSystem->getData(&comp).boundingBox;
504 auto * entity = comp.getContainer();
505 ImGui::Text("[%zu] %s", entity->getId(), entity->getName().c_str());
506 ImGui::NextColumn();
507 if(bb.min.x > bb.max.x){
508 ImGui::Text("max, max, max");
509 ImGui::NextColumn();
510 ImGui::Text("-max, -max, -max");
511 ImGui::NextColumn();
512 ImGui::Text("0, 0, 0");
513 }
514 else{
515 ImGui::Text("%.2f, %.2f, %.2f", bb.min.x, bb.min.y, bb.min.z);
516 ImGui::NextColumn();
517 ImGui::Text("%.2f, %.2f, %.2f", bb.max.x, bb.max.y, bb.max.z);
518 ImGui::NextColumn();
519 glm::vec3 size = bb.max-bb.min;
520 ImGui::Text("%.2f, %.2f, %.2f", size.x, size.y, size.z);
521 }
522 ImGui::NextColumn();
523 }
524 ImGui::Columns(1);
525 ImGui::TreePop();
526 }
527 if(ImGui::TreeNode("Extensions")){
528 ImGui::Columns(4, "Extensions", true);
529 for (auto & bounds : context->bounds->getExtensions()) {
530 BoundingBox bb;
531 float nearPlaneLimit = 0.f;
532 bounds->getBounds(context, bb, nearPlaneLimit);
533 ImGui::Text("extension np %.2f", nearPlaneLimit);
534 ImGui::NextColumn();
535 if(bb.min.x > bb.max.x){
536 ImGui::Text("max, max, max");
537 ImGui::NextColumn();
538 ImGui::Text("-max, -max, -max");
539 ImGui::NextColumn();
540 ImGui::Text("0, 0, 0");
541 }
542 else{
543 ImGui::Text("%.2f, %.2f, %.2f", bb.min.x, bb.min.y, bb.min.z);
544 ImGui::NextColumn();
545 ImGui::Text("%.2f, %.2f, %.2f", bb.max.x, bb.max.y, bb.max.z);
546 ImGui::NextColumn();
547 glm::vec3 size = bb.max-bb.min;
548 ImGui::Text("%.2f, %.2f, %.2f", size.x, size.y, size.z);
549 }
550 ImGui::NextColumn();
551 }
552 ImGui::Columns(1);
553 ImGui::TreePop();
554 }
555 }
556
557 guiEnd();
558}
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.
Definition: Context.h:83
std::unique_ptr< class Bounds > bounds
Bounds service instance.
Definition: Context.h:216
void setOrigin(const glm::dvec3 &newOrigin)
Sets the Origin offset of the scene.
glm::dvec3 getOrigin() const
Gets the Origin offset of the scene.
Log implementation class.
Definition: LogManager.h:139
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....
COGSCORE_DLL_API SimplexResult simplexMaximize(Context *context, uintptr_t scratch, double *solutions, const int variableCount, const double *objectives, const int objectiveCount, const double *restrictions, const int restrictionCount, const int maxIterationCount, const bool printSteps=false)
Find the maximum of a linear programming problem using the simplex method.
Definition: Simplex.cpp:452
COGSCORE_DLL_API size_t simplexScratchSize(const size_t variableCount, const size_t objectiveCount, const size_t restrictionCount)
Number of bytes of scratch array required by simplexMaximize.
Definition: Simplex.cpp:440
RenderLayers
Contains common render layers.
Contains geometry calculations and generation.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Definition: LogManager.h:180