Skip to content

Commit 55abf77

Browse files
committed
Make left drag work with pick rays
1 parent ed5d1cb commit 55abf77

File tree

2 files changed

+51
-28
lines changed

2 files changed

+51
-28
lines changed

src/celestia/celestiacore.cpp

Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,11 @@ void CelestiaCore::mouseButtonDown(float x, float y, int button)
407407
{
408408
mouseMotion = 0.0f;
409409

410+
MouseLocation newLocation;
411+
newLocation.x = x;
412+
newLocation.y = y;
413+
dragLocation = newLocation;
414+
410415
#ifdef CELX
411416
if (m_script != nullptr)
412417
{
@@ -429,6 +434,8 @@ void CelestiaCore::mouseButtonDown(float x, float y, int button)
429434

430435
void CelestiaCore::mouseButtonUp(float x, float y, int button)
431436
{
437+
dragLocation = std::nullopt;
438+
432439
// Four pixel tolerance for picking
433440
float obsPickTolerance = sim->getActiveObserver()->getFOV() / static_cast<float>(metrics.height) * this->pickTolerance;
434441

@@ -454,17 +461,7 @@ void CelestiaCore::mouseButtonUp(float x, float y, int button)
454461
{
455462
viewManager->pickView(sim, metrics, x, y);
456463

457-
float pickX;
458-
float pickY;
459-
float aspectRatio = static_cast<float>(metrics.width) / static_cast<float>(metrics.height);
460-
viewManager->activeView()->mapWindowToView(x / static_cast<float>(metrics.width),
461-
y / static_cast<float>(metrics.height),
462-
pickX, pickY);
463-
pickX *= aspectRatio;
464-
if (isViewportEffectUsed)
465-
viewportEffect->distortXY(pickX, pickY);
466-
467-
Vector3f pickRay = renderer->getProjectionMode()->getPickRay(pickX, pickY, viewManager->activeView()->getObserver()->getZoom());
464+
Vector3f pickRay = getPickRay(x, y, viewManager->activeView());
468465

469466
Selection oldSel = sim->getSelection();
470467
Selection newSel = sim->pickObject(pickRay, renderer->getRenderFlags(), obsPickTolerance);
@@ -560,6 +557,13 @@ void CelestiaCore::mouseMove(float x, float y)
560557

561558
void CelestiaCore::mouseMove(float dx, float dy, int modifiers)
562559
{
560+
auto oldLocation = dragLocation;
561+
if (dragLocation.has_value())
562+
{
563+
dragLocation.value().x += dx;
564+
dragLocation.value().y += dy;
565+
}
566+
563567
if (viewManager->resizeViews(metrics, dx, dy))
564568
{
565569
setFOVFromZoom();
@@ -652,27 +656,21 @@ void CelestiaCore::mouseMove(float dx, float dy, int modifiers)
652656
flash(fmt::sprintf(_("Magnitude limit: %.2f"), sim->getFaintestVisible()));
653657
}
654658
}
655-
else
659+
else if ((modifiers & RightButton) != 0)
656660
{
657-
// For a small field of view, rotate the camera more finely
658-
float coarseness = 1.5f;
659-
if ((modifiers & RightButton) == 0)
660-
{
661-
coarseness = math::radToDeg(sim->getActiveObserver()->getFOV()) / 30.0f;
662-
}
663-
else
664-
{
665-
// If right dragging to rotate, adjust the rotation rate
666-
// based on the distance from the reference object.
667-
coarseness = ComputeRotationCoarseness(*sim);
668-
}
661+
// Adjust the rotation rate based on the distance from the reference object.
662+
float coarseness = ComputeRotationCoarseness(*sim);
669663

670664
Quaternionf q = math::XRotation(dy / static_cast<float>(metrics.height) * coarseness) *
671665
math::YRotation(dx / static_cast<float>(metrics.width) * coarseness);
672-
if ((modifiers & RightButton) != 0)
673-
sim->orbit(q);
674-
else
675-
sim->rotate(q.conjugate());
666+
sim->orbit(q);
667+
}
668+
else if (oldLocation.has_value() && dragLocation.has_value())
669+
{
670+
auto view = viewManager->activeView();
671+
auto oldPickRay = getPickRay(oldLocation.value().x, oldLocation.value().y, view);
672+
auto newPickRay = getPickRay(dragLocation.value().x, dragLocation.value().y, view);
673+
sim->rotate(Eigen::Quaternionf::FromTwoVectors(oldPickRay, newPickRay));
676674
}
677675

678676
mouseMotion += abs(dy) + abs(dx);
@@ -2216,6 +2214,22 @@ void CelestiaCore::renderOverlay()
22162214
}
22172215

22182216

2217+
Eigen::Vector3f CelestiaCore::getPickRay(float x, float y, const celestia::View *view)
2218+
{
2219+
float pickX;
2220+
float pickY;
2221+
float aspectRatio = static_cast<float>(metrics.width) / static_cast<float>(metrics.height);
2222+
view->mapWindowToView(x / static_cast<float>(metrics.width),
2223+
y / static_cast<float>(metrics.height),
2224+
pickX, pickY);
2225+
pickX *= aspectRatio;
2226+
if (isViewportEffectUsed)
2227+
viewportEffect->distortXY(pickX, pickY);
2228+
2229+
return renderer->getProjectionMode()->getPickRay(pickX, pickY, view->getObserver()->getZoom());
2230+
}
2231+
2232+
22192233
class SolarSystemLoader
22202234
{
22212235
Universe* universe;

src/celestia/celestiacore.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <functional>
1616
#include <string_view>
1717
#include <tuple>
18+
#include <optional>
1819
#include <celutil/filetype.h>
1920
#include <celutil/timer.h>
2021
#include <celutil/watcher.h>
@@ -404,6 +405,7 @@ class CelestiaCore // : public Watchable<CelestiaCore>
404405
void updateSelectionFromInput();
405406
bool readStars(const CelestiaConfig&, ProgressNotifier*);
406407
void renderOverlay();
408+
Eigen::Vector3f getPickRay(float x, float y, const celestia::View *view);
407409
#ifdef CELX
408410
bool initLuaHook(ProgressNotifier*);
409411
#endif // CELX
@@ -493,6 +495,13 @@ class CelestiaCore // : public Watchable<CelestiaCore>
493495

494496
float pickTolerance { 4.0f };
495497

498+
struct MouseLocation
499+
{
500+
float x;
501+
float y;
502+
};
503+
std::optional<MouseLocation> dragLocation{ std::nullopt };
504+
496505
std::unique_ptr<ViewportEffect> viewportEffect { nullptr };
497506
bool isViewportEffectUsed { false };
498507

0 commit comments

Comments
 (0)