4#include "EntityStore.h"
6#include "Components/Core/MeshRenderComponent.h"
7#include "Components/Core/SceneComponent.h"
8#include "Components/Core/NearLimitComponent.h"
10#include "Foundation/ComponentModel/Component.h"
11#include "Systems/Core/MeshSystem.h"
12#include "Systems/Core/CameraSystem.h"
13#include "Systems/Core/TransformSystem.h"
14#include "Systems/Core/RenderSystem.h"
15#include "Systems/Core/SubMeshRenderSystem.h"
16#include "Systems/Core/StaticModelSystem.h"
17#include "Systems/Core/SpriteRenderSystem.h"
19#include "Platform/Instrumentation.h"
21#include "Rendering/DataFormat.h"
23#include "Resources/MeshManager.h"
24#include "Resources/Buffer.h"
26#include "Utilities/Parallel.h"
27#include "Utilities/Simplex.h"
29#include "Foundation/Geometry/BoundingBox.hpp"
30#include "Foundation/Geometry/Glm.hpp"
31#include "Foundation/Logging/Logger.h"
33#include <glm/gtc/packing.hpp>
46 void entityError(
const EntityId entityId)
48 LOG_ERROR(logger,
"Invalid entity id %zd.",
size_t(entityId));
51 template<
typename T, glm::precision P>
52 glm::tvec3<T, P> transformWithDivision(glm::tvec3<T, P> v, glm::tmat4x4<T, P> m)
54 auto hV = glm::tvec4<T, P>(v.x, v.y, v.z, 1);
57 return glm::tvec3<T, P>(r.x / r.w, r.y / r.w, r.z / r.w);
62 return renderSystem->getWorldBounds(meshComponent);
67 return subMeshRenderSystem->getWorldBounds(meshComponent);
72 return context->spriteRenderSystem->getData(sprite).boundingBox;
75 [[nodiscard]] BoundingBox getBounds(
Context * context,
const Entity * entity,
bool ignoreVisibility)
83 if (meshRenderComponent && (ignoreVisibility || meshRenderComponent->
isVisible()) && meshComp && meshComp->meshHandle) {
84 return getMeshBounds(entityData->
entityContext->renderSystem, meshRenderComponent);
90 if (meshRenderComponent && (ignoreVisibility || meshRenderComponent->
isVisible()) && meshComp && meshComp->meshHandle) {
91 return getMeshBounds(context->renderSystem, meshRenderComponent);
96 if (spriteRenderComponent && spriteRenderComponent->
isVisible()) {
97 return getSpriteBounds(context, spriteRenderComponent);
100 BoundingBox extensionBounds;
101 for (
auto & bounds : context->
bounds->getExtensions()) {
102 if (bounds->getBounds(context, entity, extensionBounds, ignoreVisibility))
103 return extensionBounds;
107 return BoundingBox();
110 BoundingBox getBoundsWithChildren(
Context * context,
const Entity * entity,
bool ignoreVisibility)
114 if (staticModelComponent) {
115 auto renderSystem = context->staticModelSystem->getRenderSystem(staticModelComponent);
120 for (
auto& rc : renderSystem->
pool) {
121 bbox += renderSystem->getWorldBounds(&rc);
128 auto box = getBounds(context, entity, ignoreVisibility);
131 if (!sceneComponent)
return box;
133 for (
auto & child : sceneComponent->
children) {
134 box += getBoundsWithChildren(context, child.get(), ignoreVisibility);
141 bool isInside(
const glm::vec3& point,
const BoundingBox& bbox)
143 return point.x >= bbox.min.x && point.x <= bbox.max.x &&
144 point.y >= bbox.min.y && point.y <= bbox.max.y &&
145 point.z >= bbox.min.z && point.z <= bbox.max.z;
148 void findNearFarFromMeshVerts(
const Mesh& mesh,
const glm::mat4& worldViewProj,
const glm::mat4& inverseProj,
float& viewNear,
float& viewFar)
150 const uint8_t* posData =
nullptr;
151 Cogs::DataFormat posFormat = Cogs::DataFormat::Unknown;
152 uint32_t posStride = 0;
153 uint32_t posCount = 0;
156 for (
size_t i = 0; i < VertexDataType::LastVertexType; ++i) {
159 const DataStream& stream = mesh.streams[mesh.streamIndexes[vertexType]];
164 posFormat = element.
format;
165 posStride = stream.
stride;
173 if (posData ==
nullptr || posCount == 0) {
177 glm::vec3 nearLocal{std::numeric_limits<float>::max()};
178 glm::vec3 farLocal{std::numeric_limits<float>::min()};
182 case Cogs::DataFormat::R10G10B10A2_UINT: {
183 for (uint32_t i = 0; i < posCount; i++) {
184 glm::vec3 pos = glm::unpackU3x10_1x2(*
reinterpret_cast<const uint32_t*
>(posData + posStride * i));
185 const glm::vec4 posInClip = worldViewProj * glm::vec4{ pos, 1.f };
187 if (-posInClip.w <= posInClip.x && posInClip.x <= posInClip.w &&
188 -posInClip.w <= posInClip.y && posInClip.y <= posInClip.w) {
189 const float z = posInClip.z / posInClip.w;
191 if (z < nearLocal.z) {
192 nearLocal = {posInClip.x / posInClip.w, posInClip.y / posInClip.w, z};
194 if (z > farLocal.z) {
195 farLocal = {posInClip.x / posInClip.w, posInClip.y / posInClip.w, z};
202 case Cogs::DataFormat::R10G10B10A2_UNORM: {
203 const float scaleFactor = (1.f / 1023.f);
204 for (uint32_t i = 0; i < posCount; i++) {
205 glm::vec3 pos = glm::vec3(glm::unpackU3x10_1x2(*
reinterpret_cast<const uint32_t*
>(posData + posStride * i))) * scaleFactor;
206 const glm::vec4 posInClip = worldViewProj * glm::vec4{ pos, 1.f };
208 if (-posInClip.w <= posInClip.x && posInClip.x <= posInClip.w &&
209 -posInClip.w <= posInClip.y && posInClip.y <= posInClip.w) {
210 const float z = posInClip.z / posInClip.w;
212 if (z < nearLocal.z) {
213 nearLocal = {posInClip.x / posInClip.w, posInClip.y / posInClip.w, z};
215 if (z > farLocal.z) {
216 farLocal = {posInClip.x / posInClip.w, posInClip.y / posInClip.w, z};
223 case Cogs::DataFormat::R16G16B16_UINT: {
224 const glm::u16vec3* verts =
reinterpret_cast<const glm::u16vec3*
>(posData);
225 for (uint32_t i = 0; i < posCount; i++) {
226 const glm::vec4 posInClip = worldViewProj * glm::vec4{ verts[i], 1.f };
228 if (-posInClip.w <= posInClip.x && posInClip.x <= posInClip.w &&
229 -posInClip.w <= posInClip.y && posInClip.y <= posInClip.w) {
230 const float z = posInClip.z / posInClip.w;
232 if (z < nearLocal.z) {
233 nearLocal = {posInClip.x / posInClip.w, posInClip.y / posInClip.w, z};
235 if (z > farLocal.z) {
236 farLocal = {posInClip.x / posInClip.w, posInClip.y / posInClip.w, z};
243 case Cogs::DataFormat::R16G16B16_UNORM: {
244 const glm::u16vec3* verts =
reinterpret_cast<const glm::u16vec3*
>(posData);
245 const float scaleFactor = (1.f / 0xFFFF);
246 for (uint32_t i = 0; i < posCount; i++) {
247 const glm::vec3 posInLocalSpace = glm::vec3(verts[i]) * scaleFactor;
248 const glm::vec4 posInClip = worldViewProj * glm::vec4{posInLocalSpace , 1.f };
250 if (-posInClip.w <= posInClip.x && posInClip.x <= posInClip.w &&
251 -posInClip.w <= posInClip.y && posInClip.y <= posInClip.w) {
252 const float z = posInClip.z / posInClip.w;
254 if (z < nearLocal.z) {
255 nearLocal = {posInClip.x / posInClip.w, posInClip.y / posInClip.w, z};
257 if (z > farLocal.z) {
258 farLocal = {posInClip.x / posInClip.w, posInClip.y / posInClip.w, z};
265 case Cogs::DataFormat::R16G16B16_FLOAT: {
266 for (uint32_t i = 0; i < posCount; i++) {
267 glm::vec3 pos = glm::unpackHalf4x16(*
reinterpret_cast<const uint64_t*
>(posData + posStride * i));
268 const glm::vec4 posInClip = worldViewProj * glm::vec4{ pos, 1.f };
270 if (-posInClip.w <= posInClip.x && posInClip.x <= posInClip.w &&
271 -posInClip.w <= posInClip.y && posInClip.y <= posInClip.w) {
272 const float z = posInClip.z / posInClip.w;
274 if (z < nearLocal.z) {
275 nearLocal = {posInClip.x / posInClip.w, posInClip.y / posInClip.w, z};
277 if (z > farLocal.z) {
278 farLocal = {posInClip.x / posInClip.w, posInClip.y / posInClip.w, z};
285 case Cogs::DataFormat::R32G32B32_FLOAT: {
286 const glm::vec3* verts =
reinterpret_cast<const glm::vec3*
>(posData);
287 for (uint32_t i = 0; i < posCount; i++) {
288 const glm::vec4 posInClip = worldViewProj * glm::vec4{ verts[i], 1.f };
290 if (-posInClip.w <= posInClip.x && posInClip.x <= posInClip.w &&
291 -posInClip.w <= posInClip.y && posInClip.y <= posInClip.w) {
292 const float z = posInClip.z / posInClip.w;
294 if (z < nearLocal.z) {
295 nearLocal = {posInClip.x / posInClip.w, posInClip.y / posInClip.w, z};
297 if (z > farLocal.z) {
298 farLocal = {posInClip.x / posInClip.w, posInClip.y / posInClip.w, z};
306 case Cogs::DataFormat::R32G32B32A32_FLOAT: {
307 const glm::vec4* verts =
reinterpret_cast<const glm::vec4*
>(posData);
308 for (uint32_t i = 0; i < posCount; i++) {
309 const glm::vec4 posInClip = worldViewProj * glm::vec4{ glm::vec3(verts[i]), 1.f };
311 if (-posInClip.w <= posInClip.x && posInClip.x <= posInClip.w &&
312 -posInClip.w <= posInClip.y && posInClip.y <= posInClip.w) {
313 const float z = posInClip.z / posInClip.w;
315 if (z < nearLocal.z) {
316 nearLocal = {posInClip.x / posInClip.w, posInClip.y / posInClip.w, z};
318 if (z > farLocal.z) {
319 farLocal = {posInClip.x / posInClip.w, posInClip.y / posInClip.w, z};
328 LOG_ERROR(logger,
"Unsupported position format: %s", formatInfo->
name);
333 if (nearLocal.z < std::numeric_limits<float>::max()) {
334 const glm::vec4 closest = inverseProj * glm::vec4(nearLocal, 1.f);
335 viewNear = -closest.z / closest.w;
337 if (farLocal.z > std::numeric_limits<float>::min()) {
338 const glm::vec4 farthest = inverseProj * glm::vec4(farLocal, 1.f);
339 viewFar = -farthest.z / farthest.w;
344 uint8_t* simplexScratch,
347 const BoundingBox& bbox,
348 const mat4& bboxViewMatrix,
349 const mat4& bboxViewMatrixInverse,
350 const mat4& bboxViewProjectionMatrix)
352 if(!(bbox.min.x <= bbox.max.x &&
353 bbox.min.y <= bbox.max.y &&
354 bbox.min.z <= bbox.max.z )){
358 float localNear = std::numeric_limits<float>::max();
359 float localFar = -std::numeric_limits<float>::max();
363 for (
int i = 0; i < 8; i++) {
364 vec4 t(i & 1 ? bbox.min.x : bbox.max.x,
365 i & 2 ? bbox.min.y : bbox.max.y,
366 i & 4 ? bbox.min.z : bbox.max.z,
369 vec4 c = bboxViewProjectionMatrix * t;
371 if (-c.w <= c.x) pointMask |= 0x1;
372 if (c.x <= c.w) pointMask |= 0x2;
373 if (-c.w <= c.y) pointMask |= 0x4;
374 if (c.y <= c.w) pointMask |= 0x8;
375 if (pointMask == 0xf) {
376 vec4 v = bboxViewMatrix*t;
378 assert(std::isfinite(z));
379 localNear = std::min(localNear, -z);
380 localFar = std::max(localFar, -z);
382 insideMask |= pointMask;
383 outsideMask |= ~pointMask & 0xf;
386 if(localNear >= viewNear && localFar <= viewFar){
390 if (insideMask != 0xf) {
392 }
else if (outsideMask == 0x0) {
395 viewNear = std::min(viewNear, localNear);
396 viewFar = std::max(viewFar, localFar);
400 glm::mat4 bboxMinAlignedViewProjectionMatrix = glm::translate(bboxViewProjectionMatrix, bbox.min);
401 glm::mat4 bboxMinAlignedViewMatrix = glm::translate(bboxViewMatrix, bbox.min);
406 glm::vec3 e = bbox.max - bbox.min;
407 float scale = std::max(std::max(e.x, e.y), e.z);
410 viewNear = std::min(viewNear, localNear);
411 viewFar = std::max(viewFar, localNear);
415 float epsilon = std::numeric_limits<float>::epsilon()*scale;
417 mat4 rows = glm::transpose(bboxMinAlignedViewProjectionMatrix);
418 glm::vec4 l = rows[3] + rows[0];
419 glm::vec4 r = rows[3] - rows[0];
420 glm::vec4 b = rows[3] + rows[1];
421 glm::vec4 t = rows[3] - rows[1];
428 double restrictions[7 * 4] =
431 1.0, 0.0, 0.0, std::max(epsilon, e.x),
432 0.0, 1.0, 0.0, std::max(epsilon, e.y),
433 0.0, 0.0, 1.0, std::max(epsilon, e.z),
435 -l.x, -l.y, -l.z, l.w,
436 -r.x, -r.y, -r.z, r.w,
437 -b.x, -b.y, -b.z, b.w,
438 -t.x, -t.y, -t.z, t.w,
441 double objectives[2 * 3];
442 double solutions[2 * 3];
444 bool find_far = localFar > viewFar;
445 bool find_near = localNear < viewNear;
446 int objective_count = find_near && find_far ? 2 : 1;
448 int min_idx = find_far ? 1 : 0;
451 objectives[max_idx*3+0] = -bboxViewMatrixInverse[2].x;
452 objectives[max_idx*3+1] = -bboxViewMatrixInverse[2].y;
453 objectives[max_idx*3+2] = -bboxViewMatrixInverse[2].z;
457 objectives[min_idx*3+0] = bboxViewMatrixInverse[2].x;
458 objectives[min_idx*3+1] = bboxViewMatrixInverse[2].y;
459 objectives[min_idx*3+2] = bboxViewMatrixInverse[2].z;
463 (uintptr_t)simplexScratch,
465 objectives, objective_count,
468 if (rv == SimplexResult::NoFeasibleSolutions) {
470 }
else if (rv == SimplexResult::OptimalSolutionFound) {
472 vec4 v = bboxMinAlignedViewMatrix*glm::vec4(solutions[3 * min_idx + 0],
473 solutions[3 * min_idx + 1],
474 solutions[3 * min_idx + 2],
477 assert(std::isfinite(z));
478 viewNear = std::min(viewNear, -z);
482 vec4 v = bboxMinAlignedViewMatrix*glm::vec4(solutions[3 * max_idx + 0],
483 solutions[3 * max_idx + 1],
484 solutions[3 * max_idx + 2],
487 assert(std::isfinite(z));
489 viewFar = std::max(viewFar, -z);
492 LOG_DEBUG(logger,
"Simplex optimization failed (=%d), reverting to standard approach.", (
int)rv);
493 for (
int i = 0; i < 8; i++) {
494 vec4 t_(i & 1 ? bbox.min.x : bbox.max.x,
495 i & 2 ? bbox.min.y : bbox.max.y,
496 i & 4 ? bbox.min.z : bbox.max.z,
498 vec4 v = bboxViewMatrix*t_;
500 assert(std::isfinite(z));
501 viewNear = std::min(viewNear, -z);
502 viewFar = std::max(viewFar, -z);
512 return ::getBoundsWithChildren(context, entity, ignoreVisibility);
515Cogs::Geometry::BoundingBox Cogs::Core::Bounds::getTransformedBounds(
const Cogs::Geometry::BoundingBox& bbox,
const glm::mat4 & m)
517 std::array<glm::vec3, 8> points;
518 Cogs::Geometry::corners(bbox, points);
520 for (
auto & p : points) {
524 return Cogs::Geometry::computeBoundingBox(points.begin(), points.end());
527Cogs::Geometry::BoundingBox Cogs::Core::Bounds::getTransformedBoundsWithDivision(
const Cogs::Geometry::BoundingBox& bbox,
const glm::mat4 & m)
529 std::array<glm::vec3, 8> points;
530 Cogs::Geometry::corners(bbox, points);
532 for (
auto & p : points) {
533 p = transformWithDivision(p, m);
536 return Cogs::Geometry::computeBoundingBox(points.begin(), points.end());
539Cogs::Geometry::BoundingBox Cogs::Core::Bounds::getBounds(
Context* context,
const EntityId
id,
bool ignoreVisibility)
544 return ::getBoundsWithChildren(context, entity, ignoreVisibility);
547 return BoundingBox();
550Cogs::Geometry::BoundingBox Cogs::Core::Bounds::getBounds(
Context* context, std::span<const EntityId> ids,
bool ignoreVisibility)
552 Cogs::Geometry::BoundingBox box;
554 for (
auto&
id : ids) {
558 Cogs::Geometry::BoundingBox bb = ::getBoundsWithChildren(context, entity, ignoreVisibility);
571Cogs::Geometry::BoundingBox Cogs::Core::Bounds::getSceneBounds(
Context* context,
RenderLayers layerMask)
573 Cogs::Geometry::BoundingBox box;
575 for (
auto & renderComponent : context->renderSystem->
pool) {
576 if (!renderComponent.isVisibleInLayer(layerMask))
continue;
578 const auto& bb = ::getMeshBounds(context->renderSystem, &renderComponent);
583 for (
auto & renderComponent : context->subMeshRenderSystem->
pool) {
584 if (!renderComponent.isVisibleInLayer(layerMask))
continue;
586 const auto& bb = ::getMeshBounds(context->subMeshRenderSystem, &renderComponent);
594 const auto& data = context->spriteRenderSystem->getData(&sprite);
595 auto batch = context->spriteRenderSystem->getSpriteBatch(data.batchIndex);
604 const auto& bb = ::getSpriteBounds(context, &sprite);
609 for (
auto & bounds : getExtensions()) {
610 BoundingBox extensionBounds;
612 float nearPlaneLimit = 0.f;
613 bounds->getBounds(context, extensionBounds, nearPlaneLimit);
615 box += extensionBounds;
621void Cogs::Core::Bounds::getSceneBounds(
Context* context,
float* values,
RenderLayers layerMask)
623 Cogs::Geometry::BoundingBox box = getSceneBounds(context, layerMask);
624 box.toSpan(std::span<float, 6>(values, 6));
627void Cogs::Core::Bounds::getClipPlanes(
Context* context,
float& nearDist,
float& farDist,
const CameraComponent & cameraComponent,
const glm::mat4 & viewMatrix)
629 BoundingBox sceneBounds;
634 for (
auto & renderComponent : context->renderSystem->
pool) {
635 if (!renderComponent.isVisibleInLayer(layerMask))
continue;
637 const BoundingBox& bb = ::getMeshBounds(context->renderSystem, &renderComponent);
642 for (
auto & renderComponent : context->subMeshRenderSystem->
pool) {
643 if (!renderComponent.isVisibleInLayer(layerMask))
continue;
645 const BoundingBox& bb = ::getMeshBounds(context->subMeshRenderSystem, &renderComponent);
650 for (
auto & sprite : context->spriteRenderSystem->pool) {
653 const BoundingBox& bb = ::getSpriteBounds(context, &sprite);
658 for (
auto & bounds : getExtensions()) {
659 BoundingBox extensionBounds;
661 float nearPlaneLimit = 0.f;
662 bounds->getBounds(context, extensionBounds, nearPlaneLimit);
664 if (!extensionBounds.empty()) {
665 if (!std::isnan(nearPlaneLimit) && !std::isinf(nearPlaneLimit) && nearPlaneLimit > 0.0f) {
666 extensionBounds = getTransformedBounds(extensionBounds, viewMatrix);
668 nearDist = std::max(std::min(nearDist, -extensionBounds.max.z), nearPlaneLimit);
669 farDist = std::max(farDist, -extensionBounds.min.z);
672 sceneBounds += extensionBounds;
678 if (!sceneBounds.empty()) {
679 sceneBounds = getTransformedBounds(sceneBounds, viewMatrix);
681 nearDist = std::min(nearDist, -sceneBounds.max.z);
682 farDist = std::max(farDist, -sceneBounds.min.z);
686void Cogs::Core::Bounds::getCameraDepthBounds(
Context* context,
687 float& depthBoundNear,
688 float& depthBoundFar,
691 CpuInstrumentationScope(SCOPE_BOUNDS,
"updateClippingPlanes");
694 auto & cameraData = context->cameraSystem->getData(&cameraComponent);
696 CpuInstrumentationScope(SCOPE_BOUNDS,
"updateClippingPlanes::meshes");
698 std::vector<float> nearBounds(context->meshSystem->
pool.
size(), depthBoundNear);
699 std::vector<float> farBounds(context->meshSystem->
pool.
size(), depthBoundFar);
701 bool tightBoundsInBBox = context->
variables->get(
"camera.tightBoundsInBBox",
false);
702 auto gr1 = Parallel::processComponents(context, context->renderSystem->
pool,
"Bounds::process",
705 if (!meshRenderComp.isVisibleInLayer(layerMask)) {
713 const Cogs::Geometry::BoundingBox& bbox = context->renderSystem->getWorldBounds(&meshRenderComp);
716 float nearPlaneLimit = cameraComponent.nearPlaneLimit;
723 float nb = nearBounds[i];
725 bool cameraInsideBbox = isInside(cameraData.inverseViewMatrix[3], bbox);
726 if (tightBoundsInBBox && cameraInsideBbox) {
727 const MeshRenderData& renderData = context->renderSystem->getData<MeshRenderData>(&meshRenderComp);
728 assert(renderData.meshComponent != ComponentHandle::Empty());
729 const Mesh* mesh = renderData.meshComponent.resolveComponent<MeshComponent>()->meshHandle.resolve();
730 assert(mesh != nullptr);
731 const TransformComponent* transformComp = meshRenderComp.getComponent<TransformComponent>();
732 assert(transformComp != nullptr);
733 const glm::mat4& localToWorld = context->transformSystem->getLocalToWorld(transformComp);
735 findNearFarFromMeshVerts(*mesh, cameraData.viewProjection * localToWorld, cameraData.inverseProjectionMatrix, nb, farBounds[i]);
738 std::vector<uint8_t> simplexScratch(simplexScratchSize(3, 2, 7));
739 ::updateCameraDepthBounds(context,
740 simplexScratch.data(),
742 bbox, cameraData.viewMatrix, cameraData.inverseViewMatrix, cameraData.viewProjection);
747 nearBounds[i] = std::min(nearBounds[i], std::max(nearPlaneLimit, nb));
753 auto gr2 = Parallel::processComponents(context, context->subMeshRenderSystem->
pool,
"Bounds::processSubMesh",
756 if (!subMeshRenderComp.isVisibleInLayer(layerMask)) return;
757 if (subMeshRenderComp.lod.currentLod != subMeshRenderComp.lod.selectedLod) return;
759 const Cogs::Geometry::BoundingBox& bbox = context->subMeshRenderSystem->getWorldBounds(&subMeshRenderComp);
761 float nearPlaneLimit = cameraComponent.nearPlaneLimit;
768 float nb = nearBounds[i];
770 bool cameraInsideBbox = isInside(cameraData.inverseViewMatrix[3], bbox);
771 if (tightBoundsInBBox && cameraInsideBbox) {
772 const SubMeshRenderData& renderData = context->subMeshRenderSystem->getData<SubMeshRenderData>(&subMeshRenderComp);
773 assert(renderData.meshComponent != ComponentHandle::Empty());
774 const Mesh* mesh = renderData.meshComponent.resolveComponent<MeshComponent>()->meshHandle.resolve();
775 assert(mesh != nullptr);
776 const TransformComponent* transformComp = subMeshRenderComp.getComponent<TransformComponent>();
777 assert(transformComp != nullptr);
778 const glm::mat4& localToWorld = context->transformSystem->getLocalToWorld(transformComp);
780 findNearFarFromMeshVerts(*mesh, cameraData.viewProjection * localToWorld, cameraData.inverseProjectionMatrix, nb, farBounds[i]);
783 std::vector<uint8_t> simplexScratch(simplexScratchSize(3, 2, 7));
784 ::updateCameraDepthBounds(context,
785 simplexScratch.data(),
787 bbox, cameraData.viewMatrix, cameraData.inverseViewMatrix, cameraData.viewProjection);
790 nearBounds[i] = std::min(nearBounds[i], std::max(nearPlaneLimit, nb));
796 for (
size_t i = 0; i < nearBounds.size(); ++i) {
797 depthBoundNear = std::min(depthBoundNear, nearBounds[i]);
798 depthBoundFar = std::max(depthBoundFar, farBounds[i]);
803 for (
auto & sprite : context->spriteRenderSystem->pool) {
805 auto & data = context->spriteRenderSystem->getData(&sprite);
806 if (data.batchIndex == NoBatchIndex)
continue;
807 const auto & batch = context->spriteRenderSystem->getSpriteBatch(data.batchIndex);
811 p = cameraData.viewMatrix * glm::vec4(data.position, 1);
812 }
else if(batch->positionMode == PositionMode::Local){
813 p = cameraData.viewMatrix * batch->transform * glm::vec4(data.position, 1);
818 glm::vec4 c = cameraData.projectionMatrix * p;
820 if (-c.w <= c.x) pointMask |= 0x1;
821 if (c.x <= c.w) pointMask |= 0x2;
822 if (-c.w <= c.y) pointMask |= 0x4;
823 if (c.y <= c.w) pointMask |= 0x8;
824 int outsideMask = ~pointMask & 0xf;
828 depthBoundNear = std::min(depthBoundNear, (-p.z) * (1.f - std::numeric_limits<float>::epsilon()));
829 depthBoundFar = std::max(depthBoundFar, (-p.z) * (1.f + std::numeric_limits<float>::epsilon()));
833 CpuInstrumentationScope(SCOPE_BOUNDS,
"updateClippingPlanes::extensions");
834 for (
auto & bounds : context->
bounds->getExtensions()) {
836 float nearPlaneLimit = std::numeric_limits<float>::quiet_NaN();
837 BoundingBox extensionBounds;
839 bounds->getBounds(context, extensionBounds, nearPlaneLimit);
840 if (!extensionBounds.empty()) {
842 float nb = depthBoundNear;
844 ::updateCameraDepthBounds(context,
845 simplexScratch.data(),
847 extensionBounds, cameraData.viewMatrix, cameraData.inverseViewMatrix, cameraData.viewProjection);
848 if (!std::isfinite(nearPlaneLimit)) nearPlaneLimit = cameraComponent.
nearPlaneLimit;
850 depthBoundNear = std::min(depthBoundNear, std::max(nearPlaneLimit, nb));
857Cogs::Geometry::BoundingBox Cogs::Core::Bounds::getShadowBounds(
Context* context)
862 for (
auto & renderComponent : context->renderSystem->
pool) {
863 if (!renderComponent.isVisible() || !renderComponent.castShadows())
continue;
864 if (!renderComponent.isVisibleInLayer(layerMask))
continue;
865 BoundingBox bb = ::getMeshBounds(context->renderSystem, &renderComponent);
869 for (
auto & renderComponent : context->subMeshRenderSystem->
pool) {
870 if (!renderComponent.isVisible() || !renderComponent.castShadows())
continue;
871 if (!renderComponent.isVisibleInLayer(layerMask))
continue;
872 BoundingBox bb = ::getMeshBounds(context->subMeshRenderSystem, &renderComponent);
876 for (
auto & sprite : context->spriteRenderSystem->pool) {
880 BoundingBox bb = ::getSpriteBounds(context, &sprite);
897 extensions.push_back(bounds);
902 extensions.erase(std::remove(extensions.begin(), extensions.end(), bounds), extensions.end());
SizeType size() const
Gets the current size of the pool, the number components currently active.
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.
constexpr void * getUserData() const noexcept
Get user data.
COGSCORE_DLL_API void removeBoundsExtension(IGetBounds *bounds)
De-register bounds calculation.
COGSCORE_DLL_API void addBoundsExtension(IGetBounds *bounds)
RenderLayers layerMask
Layer mask used to determine which RenderComponent instances should be visible in this cameras viewpo...
float nearPlaneLimit
Smallest value allowed to adjust near plane to.
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 Bounds > bounds
Bounds service instance.
class EntityStore * store
Entity store.
std::unique_ptr< class TaskManager > taskManager
TaskManager service instance.
std::unique_ptr< class Variables > variables
Variables service instance.
ComponentModel::Entity * getEntityPtr(const EntityId entityId)
Get a raw pointer to the entity with the given id.
Contains a handle to a Mesh resource to use when rendering using the MeshRenderComponent.
Renders the contents of a MeshComponent using the given materials.
constexpr bool isVisibleInLayer(RenderLayers layerMask) const
Check if the entity should be visible in the given layer mask.
constexpr bool isVisible() const
Check if the entity is visible or not.
RenderFlags renderFlags
Render flags used to control rendering behavior.
The mesh render system handles MeshRenderComponents.
Contains information on how the entity behaves in the scene.
std::vector< EntityPtr > children
Contains all child entities owned by this component.
Renders a mesh with flexible submesh usage.
The submesh render system handles SubMeshRenderComponents.
Log implementation class.
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.
@ Relative
Position given in normalized device coordinates, with [-1, -1] corresponding to the lower left of the...
@ Pixels
Position given in screen pixels ranging from [0, 0] in the lower left corner to [viewport....
@ World
Position given in world space coordinates.
@ CastShadows
Casts shadows.
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.
RenderLayers
Contains common render layers.
Contains geometry calculations and generation.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
@ Position
Position semantic.
void * data()
Get a pointer to the buffer data.
Contains a stream of data used by Mesh resources.
uint32_t numElements
Number of elements of the type given by format contained in data.
uint32_t offset
Byte offset from the start of the buffer.
VertexFormatHandle format
A pointer to the format describing the contents of the byte buffer.
uint32_t stride
Element stride.
Cogs::Core::ResourceBufferHandle buffer
Data buffer.
Holds extra housekeeping data for an Entity instance.
ContextBase * entityContext
Pointer to the ContextBase the entity belongs to.
Meshes contain streams of vertex data in addition to index data and options defining geometry used fo...
bool hasStream(VertexDataType::EVertexDataType type) const
Check if the Mesh has a DataStream for the given type.
uint8_t currentLod
The assigned LoD of the current component.
uint8_t selectedLod
The selected LoD of the composite entity.
EVertexDataType
Contains data types.
Vertex element structure used to describe a single data element in a vertex for the input assembler.
DataFormat format
Format of the element.
uint16_t offset
Offset in bytes from the vertex position in memory.
uint16_t semanticIndex
Index for the semantic mapping.
ElementSemantic semantic
Semantic mapping of the element (position, normal, etc...).