3D: ray cast — ищем ближайший атом вдоль луча
| 141 | |
| 142 | // 3D: ray cast — ищем ближайший атом вдоль луча |
| 143 | bool PickingSystem::pickAtom3D(glm::ivec2 screenPos, AtomHit& hit) const { |
| 144 | const RenderRay ray = (*renderer)->camera.screenToRay(screenPos.x, screenPos.y); |
| 145 | |
| 146 | float bestT = std::numeric_limits<float>::max(); |
| 147 | size_t bestIndex = static_cast<size_t>(-1); |
| 148 | |
| 149 | for (size_t i = 0; i < atomStorage->size(); ++i) { |
| 150 | const glm::vec3 worldPos = displayAtomPos(i); |
| 151 | const float radius = AtomData::getProps(atomStorage->type(i)).radius; |
| 152 | |
| 153 | RenderRaySphereHit rayHit{}; |
| 154 | if (renderRaySphereIntersect(ray, worldPos, radius, rayHit)) { |
| 155 | if (rayHit.t < bestT) { |
| 156 | bestT = rayHit.t; |
| 157 | bestIndex = i; |
| 158 | } |
| 159 | } |
| 160 | } |
| 161 | |
| 162 | if (bestIndex == static_cast<size_t>(-1)) { |
| 163 | return false; |
| 164 | } |
| 165 | |
| 166 | hit = {bestIndex, atomStorage->atomId(bestIndex), bestT}; |
| 167 | return true; |
| 168 | } |
| 169 | |
| 170 | glm::vec3 PickingSystem::displayAtomPos(size_t atomIndex) const { |
| 171 | return atomStorage->pos(atomIndex) + box->getRenderOffset(); |
nothing calls this directly
no test coverage detected