1#include "BadgeSetPicker.h"
2#include "BadgeSetSystem.h"
5#include "ViewContext.h"
6#include "Components/Core/SceneComponent.h"
7#include "Components/Core/TransformComponent.h"
8#include "Systems/Core/TransformSystem.h"
9#include "Scene/RayPick.h"
10#include "Services/DPIService.h"
11#include "Resources/Mesh.h"
12#include "Systems/Core/CameraSystem.h"
13#include "Utilities/Math.h"
14#include "Systems/ComponentSystem.h"
16#include "Rendering/IGraphicsDevice.h"
17#include "Rendering/ICapabilities.h"
19#include "Foundation/Logging/Logger.h"
31 BoundingBox (
float minX,
float minY,
float maxX,
float maxY) {
38 bool isPointWithin(
const glm::vec2 &mouse)
const {
39 return mouse.x >= min.x && mouse.x <= max.x && mouse.y >= min.y && mouse.y <= max.y;
45 std::vector<RayPicking::RayPickHit>& hits;
49 const glm::mat4& worldFromLocal;
50 const float rayFromLocalScale;
52 bool returnChildEntity;
53 bool hitSomething =
false;
55 void operator()(
const glm::vec4& posLocal,
const float distanceLocal,
size_t index) {
56 glm::vec4 posWorld = worldFromLocal * posLocal;
57 const float distanceWorld = rayFromLocalScale * distanceLocal;
58 if (returnClosest && !hits.empty()) {
59 if (hits[0].isBehind(ordinal, distanceWorld)) {
60 hits[0] = { renderComp, returnChildEntity, glm::vec3(posWorld), ordinal, distanceWorld, glm::vec2(
static_cast<float>(index)) };
66 hits.emplace_back(renderComp, returnChildEntity, glm::vec3(posWorld), ordinal, distanceWorld, glm::vec2(
static_cast<float>(index)));
73 void pickScaledFixedScreenSizeBox(RecordHit& recordHit,
76 const glm::vec3& rayOriginLocal,
77 const glm::vec3& rayUnitDirectionLocal,
78 const glm::mat4& clipFromLocal,
79 const glm::vec2& queryClip,
80 const glm::vec2 viewportSize,
81 const float maxDistanceLocal,
86 const float size = comp.
badgeSize * dpiScale;
87 const glm::vec4 viewPlaneLocal = data.viewPlaneLocal;
88 const glm::vec3 mainCamViewDirLocal(data.viewPlaneLocal);
89 const glm::vec2 pickPosView = queryClip * viewportSize;
90 const float rcp = -1.f / glm::dot(mainCamViewDirLocal, rayUnitDirectionLocal);
91 const float mp = glm::dot(mainCamViewDirLocal, rayOriginLocal);
92 if (std::isfinite(rcp)) {
93 for (
size_t i = 0; i < comp.
positions.size(); i++) {
94 const glm::vec4 posLocal(comp.
positions[i], 1.f);
95 float viewZ = glm::dot(viewPlaneLocal, posLocal);
97 float adjustedPointSize = size * scaleFactor;
100 glm::vec2 corners[2] = {
105 glm::vec3 cornerBottomLeft = glm::vec3(posLocal) + ((adjustedPointSize * corners[0].x) * data.viewXLocal + (adjustedPointSize * corners[0].y) * data.viewYLocal);
106 glm::vec3 cornerTopRight = glm::vec3(posLocal) + ((adjustedPointSize * corners[1].x) * data.viewXLocal + (adjustedPointSize * corners[1].y) * data.viewYLocal);
108 if (nearDistance <= viewZ && viewZ <= farDistance) {
110 glm::vec3 cornerBottomLeftClipSpace = euclidean(clipFromLocal * glm::vec4(cornerBottomLeft, 1));
111 glm::vec2 cornerBottomLeftView = glm::vec2(cornerBottomLeftClipSpace) * viewportSize;
113 glm::vec3 cornerTopRightClipSpace = euclidean(clipFromLocal * glm::vec4(cornerTopRight, 1));
114 glm::vec2 cornerTopRightView = glm::vec2(cornerTopRightClipSpace) * viewportSize;
116 BoundingBox box(cornerBottomLeftView.x, cornerBottomLeftView.y, cornerTopRightView.x, cornerTopRightView.y);
117 const float t = rcp * (mp - glm::dot(glm::vec3(data.viewPlaneLocal), glm::vec3(posLocal)));
119 if (box.isPointWithin(pickPosView)) {
120 recordHit(posLocal, t, i);
131 const glm::vec2& queryClip,
133 float rayPixelRadius,
137 std::vector<RayPicking::RayPickHit>& hits)
139 const CameraData& cameraData = context->cameraSystem->getData(&camera);
140 const float dpiScale = context->getDefaultView()->
dpiService->getScaleFactor();
142 bool hitSomething =
false;
161 const glm::mat4 worldFromLocal = context->transformSystem->getLocalToWorld(transformComp);
162 const glm::mat4 clipFromLocal = cameraData.rawViewProjection * worldFromLocal;
163 const glm::mat4 localFromClip = glm::inverse(clipFromLocal);
164 const glm::vec2 sigma = glm::vec2(2.f * rayPixelRadius) / cameraData.viewportSize;
165 const glm::vec3 rayOriginLocal = euclidean(localFromClip * glm::vec4(queryClip, -1.f, 1.f));
166 const glm::vec3 rayOriginFarLocal = euclidean(localFromClip * glm::vec4(queryClip, 1.f, 1.f));
167 const glm::vec3 rayDirLocal = rayOriginFarLocal - rayOriginLocal;
168 const glm::vec3 rayOriginSigmaLocal = euclidean(localFromClip * glm::vec4(queryClip + sigma, -1.f, 1.f));
169 const glm::vec3 rayOriginSigmaFarLocal = euclidean(localFromClip * glm::vec4(queryClip + sigma, 1.f, 1.f));
170 const float rayLengthRcp = 1.f / glm::length(rayDirLocal);
171 const glm::vec3 rayUnitDirLocal = rayLengthRcp * rayDirLocal;
172 const float worldFromLocalScale = glm::determinant(glm::mat3(worldFromLocal));
175 const float maxDistanceLocal = std::min(std::numeric_limits<float>::max(), 2.f * worldFromLocalScale * rayLength);
180 .ordinal = filter.getOrdinal(*renderComp),
181 .renderComp = *renderComp,
182 .worldFromLocal = worldFromLocal,
183 .rayFromLocalScale = worldFromLocalScale,
188 pickScaledFixedScreenSizeBox(recordHit, comp, data, rayOriginLocal, rayUnitDirLocal, clipFromLocal, queryClip, cameraData.viewportSize, maxDistanceLocal, dpiScale);
190 hitSomething |= recordHit.hitSomething;
ComponentType * getComponent() const
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.
Base component for all rendering content.
constexpr bool isVisibleInLayer(RenderLayers layerMask) const
Check if the entity should be visible in the given layer mask.
Contains information on how the entity behaves in the scene.
bool visible
If the entity this component is a member of should be visible.
bool pickable
If the entity this component is a member of should be pickable.
std::unique_ptr< class DPIService > dpiService
DPI service instance.
Log implementation class.
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....
PicksReturned
* Options for returning picking hits.
@ Closest
Return just the closest hit.
PickingFlags
Options for COGS picking.
@ ReturnChildEntity
Return ID if sub-entity picked, not set: return root parent entity.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Component for showing lots of badges.
float nearScalingCutoff
Determines the near limit where the badge stops scaling freely.
float farScalingCutoff
Determines the far limit where the badge stops scaling freely.
std::vector< glm::vec3 > positions
Badge positions.
float farVisibilityLimit
Don't display badges further than this distance from the camera.
glm::vec2 boundingBoxLower
Position of the lower corner of the bounding box.
float nearVisibilityLimit
Don't display badges closer than this distance from the camera.
float badgeSize
Size of the badge.
glm::vec2 boundingBoxUpper
Position of the upper corner of the bounding box.
glm::vec2 anchorPoint
The location where the badge is anchored.
bool pickCamera(Context *context, const CameraComponent &camera, const glm::vec2 &queryClip, float, float rayRadius, PickingFlags pickingFlags, PicksReturned returnFlag, const RayPicking::RayPickFilter &filter, std::vector< RayPicking::RayPickHit > &hits) override
Contains data describing a Camera instance and its derived data structured such as matrix data and vi...
bool isUnwantedType(const ComponentModel::Component &comp) const
Helper function used to determine if a given component belongs to an accepted entity type.
RenderLayers layerMask
Limit picking to the specified render layers. Pick all layers by default.