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);
42 size_t N = std::min(hrComp.
position.size(), hrComp.
scale.size());
43 for (
size_t i = 0; i < N; i++) {
44 const glm::vec3 a = hrComp.
position[i] - nPos_local;
45 const float proj_dir_a = dot(a, dir_local);
46 const glm::vec3 nearestPointOnLine = proj_dir_a * dir_local;
48 constexpr float sqrt3 = 1.74f;
49 const float d2 = glm::distance2(a, nearestPointOnLine);
50 const float s = sqrt3 * std::max(hrComp.
scale[i].x, std::max(hrComp.
scale[i].y, hrComp.
scale[i].z));
51 if (s * s < d2)
continue;
55 glm::mat4 localFromInstance = glm::transpose(glm::mat4(instance.data0[0],
58 glm::vec4(0, 0, 0, 1)));
60 glm::mat4 instanceFromLocal = glm::mat4(glm::transpose(glm::mat3(localFromInstance)));
61 instanceFromLocal[3] = glm::vec4(-glm::mat3(instanceFromLocal) * glm::vec3(localFromInstance[3]), 1.f);
63 glm::vec3 scale = glm::vec3(instance.data1[0]);
65 glm::vec3 npos_instance = glm::vec3(instanceFromLocal * glm::vec4(nPos_local, 1.f));
66 glm::vec3 fpos_instance = glm::vec3(instanceFromLocal * glm::vec4(fPos_local, 1.f));
68 glm::vec3 dir = fpos_instance - npos_instance;
69 glm::vec3 invDir = 1.f / dir;
71 glm::vec3 nHits = invDir * (-glm::sign(dir) * scale - npos_instance);
72 glm::vec3 fHits = invDir * ( glm::sign(dir) * scale - npos_instance);
74 float t_n = std::max(nHits.x, std::max(nHits.y, nHits.z));
75 float t_f = std::min(fHits.x, std::min(fHits.y, fHits.z));
76 if (t_f < t_n)
continue;
81 glm::vec4 n = *viewMatrix * glm::vec4((1.f - t_n) * rayNear_engine + t_n * rayFar_engine, 1.f);
82 glm::vec4 f = *viewMatrix * glm::vec4((1.f - t_f) * rayNear_engine + t_f * rayFar_engine, 1.f);
87 enter = rayLength * t_n;
88 exit = rayLength * t_f;
93 std::sort(hits.begin(), hits.end());
96 if (
auto it = std::lower_bound(hits.begin(), hits.end(), enter,
99 return hit.distance < distance;
100 }); it != hits.end())
102 for (; it != hits.end() && it->distance <= exit; ++it) {
103 it->textureCoords.y =
static_cast<float>(hrComp.
id[i]);
118 const glm::vec2& normPosition,
124 std::vector<RayPicking::RayPickHit>& hits)
126 if (!hrSystem)
return false;
128 const CameraData& camData = context->cameraSystem->getData(&camComp);
129 glm::vec3 rayNear_engine = euclidean(camData.inverseViewProjectionMatrix * glm::vec4(normPosition.x, normPosition.y, -1.f, 1.f));
130 glm::vec3 rayFar_engine = euclidean(camData.inverseViewProjectionMatrix * glm::vec4(normPosition.x, normPosition.y, 1.f, 1.f));
131 float rayLength = glm::length(rayFar_engine - rayNear_engine);
132 return pickCameraImpl(context, *hrSystem, rayNear_engine, rayFar_engine, &camData.viewMatrix, rayLength, filter, hits);
136 const glm::vec3& startPos,
137 const glm::quat& rot,
143 std::vector<RayPicking::RayPickHit>& hits)
145 if (!hrSystem)
return false;
146 const glm::vec3 endPos = startPos - rot * glm::vec3(0, 0, rayLength);
147 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.