1#include "HighlightRegionPicker.h"
2#include "Systems/Core/CameraSystem.h"
3#include "Systems/Core/TransformSystem.h"
4#include "Utilities/Math.h"
7#include "HighlightRegionSystem.h"
14 bool pickCameraImpl(
Context* context,
16 const glm::vec3& rayNear_engine,
17 const glm::vec3& rayFar_engine,
18 const glm::mat4* viewMatrix,
19 const float rayLength,
21 std::vector<RayPicking::RayPickHit>& hits)
23 if (hits.empty())
return false;
25 bool hitSomething =
false;
26 bool haveSorted =
false;
35 const glm::mat4& engineFromLocal_hr = context->transformSystem->getLocalToWorld(trComp_hr);
36 const glm::mat4 localFromEngine_hr = glm::inverse(engineFromLocal_hr);
38 const glm::vec3 nPos_local = localFromEngine_hr * glm::vec4(rayNear_engine, 1.f);
39 const glm::vec3 fPos_local = localFromEngine_hr * glm::vec4(rayFar_engine, 1.f);
40 const glm::vec3 dir_local = glm::normalize(fPos_local - nPos_local);
44 size_t N = std::min(hrComp.
position.size(), hrComp.
scale.size());
45 for (
size_t i = 0; i < N; i++) {
46 const glm::vec3 a = hrComp.
position[i] - nPos_local;
47 const float proj_dir_a = dot(a, dir_local);
48 const glm::vec3 nearestPointOnLine = proj_dir_a * dir_local;
50 constexpr float sqrt3 = 1.74f;
51 const float d2 = glm::distance2(a, nearestPointOnLine);
52 const float s = sqrt3 * std::max(hrComp.
scale[i].x, std::max(hrComp.
scale[i].y, hrComp.
scale[i].z));
53 if (s * s < d2)
continue;
57 glm::mat4 localFromInstance = glm::transpose(glm::mat4(instance.data0[0],
60 glm::vec4(0, 0, 0, 1)));
62 glm::mat4 instanceFromLocal = glm::mat4(glm::transpose(glm::mat3(localFromInstance)));
63 instanceFromLocal[3] = glm::vec4(-glm::mat3(instanceFromLocal) * glm::vec3(localFromInstance[3]), 1.f);
65 glm::vec3 scale = glm::vec3(instance.data1[0]);
67 glm::vec3 npos_instance = glm::vec3(instanceFromLocal * glm::vec4(nPos_local, 1.f));
68 glm::vec3 fpos_instance = glm::vec3(instanceFromLocal * glm::vec4(fPos_local, 1.f));
70 glm::vec3 dir = fpos_instance - npos_instance;
71 glm::vec3 invDir = 1.f / dir;
73 glm::vec3 nHits = invDir * (-glm::sign(dir) * scale - npos_instance);
74 glm::vec3 fHits = invDir * ( glm::sign(dir) * scale - npos_instance);
76 float t_n = std::max(nHits.x, std::max(nHits.y, nHits.z));
77 float t_f = std::min(fHits.x, std::min(fHits.y, fHits.z));
78 if (t_f < t_n)
continue;
83 glm::vec4 n = *viewMatrix * glm::vec4((1.f - t_n) * rayNear_engine + t_n * rayFar_engine, 1.f);
84 glm::vec4 f = *viewMatrix * glm::vec4((1.f - t_f) * rayNear_engine + t_f * rayFar_engine, 1.f);
89 enter = rayLength * t_n;
90 exit = rayLength * t_f;
95 std::sort(hits.begin(), hits.end());
98 if (
auto it = std::lower_bound(hits.begin(), hits.end(), enter,
102 return hit.isInfront(ordinal, distance);
103 }); it != hits.end())
106 for (; it != hits.end() && !it->isBehind(ordinal, exit); ++it) {
107 it->textureCoords.y =
static_cast<float>(hrComp.
id[i]);
122 const glm::vec2& normPosition,
128 std::vector<RayPicking::RayPickHit>& hits)
130 if (!hrSystem)
return false;
132 const CameraData& camData = context->cameraSystem->getData(&camComp);
133 glm::vec3 rayNear_engine = euclidean(camData.inverseViewProjectionMatrix * glm::vec4(normPosition.x, normPosition.y, -1.f, 1.f));
134 glm::vec3 rayFar_engine = euclidean(camData.inverseViewProjectionMatrix * glm::vec4(normPosition.x, normPosition.y, 1.f, 1.f));
135 float rayLength = glm::length(rayFar_engine - rayNear_engine);
136 return pickCameraImpl(context, *hrSystem, rayNear_engine, rayFar_engine, &camData.viewMatrix, rayLength, filter, hits);
140 const glm::vec3& startPos,
141 const glm::quat& rot,
147 std::vector<RayPicking::RayPickHit>& hits)
149 if (!hrSystem)
return false;
150 const glm::vec3 endPos = startPos - rot * glm::vec3(0, 0, rayLength);
151 return pickCameraImpl(context, *hrSystem, startPos, endPos,
nullptr, rayLength, filter, hits);
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.
std::vector< glm::vec3 > position
Instance positions.
std::vector< glm::vec3 > scale
Instance scale factors.
std::vector< uint32_t > id
Instance ids.
Base component for all rendering content.
constexpr bool isVisibleInLayer(RenderLayers layerMask) const
Check if the entity should be visible in the given layer mask.
constexpr bool isPickable() const
Check if the entity is pickable or not.
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....
PicksReturned
* Options for returning picking hits.
PickingFlags
Options for COGS picking.
Contains data describing a Camera instance and its derived data structured such as matrix data and vi...
bool pickCamera(Context *context, const CameraComponent &camera, const glm::vec2 &normPosition, float, float radius, PickingFlags pickingFlags, PicksReturned returnFlag, const RayPicking::RayPickFilter &filter, std::vector< RayPicking::RayPickHit > &hits) override
Do a ray pick from a normalized screen space position in the camera direction and return all hits.
bool pickRay(Context *, const glm::vec3 &startPos, const glm::quat &rot, float rayLength, float radius, PickingFlags pickingFlags, PicksReturned returnFlag, const RayPicking::RayPickFilter &filter, std::vector< RayPicking::RayPickHit > &hits) override
Do a ray pick from a position and orientation in world space and return all hits.
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.