Skip to content

Commit

Permalink
explicit buffer vs screen coords for picking & screen-space ops (#259)
Browse files Browse the repository at this point in the history
  • Loading branch information
nmwsharp authored Mar 10, 2024
1 parent addce9c commit 45c86fc
Show file tree
Hide file tree
Showing 7 changed files with 37 additions and 14 deletions.
6 changes: 4 additions & 2 deletions examples/demo-app/demo_app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -769,15 +769,17 @@ void callback() {
ImGuiIO& io = ImGui::GetIO();
if (io.MouseClicked[0]) {
glm::vec2 screenCoords{io.MousePos.x, io.MousePos.y};
int xInd, yInd;
std::tie(xInd, yInd) = polyscope::view::screenCoordsToBufferInds(screenCoords);

glm::vec3 worldRay = polyscope::view::screenCoordsToWorldRay(screenCoords);
glm::vec3 worldPos = polyscope::view::screenCoordsToWorldPosition(screenCoords);
std::pair<polyscope::Structure*, size_t> pickPair =
polyscope::pick::evaluatePickQuery(screenCoords.x, screenCoords.y);
std::pair<polyscope::Structure*, size_t> pickPair = polyscope::pick::pickAtScreenCoords(screenCoords);

std::cout << "Polyscope scene test click " << std::endl;
std::cout << " io.MousePos.x: " << io.MousePos.x << " io.MousePos.y: " << io.MousePos.y << std::endl;
std::cout << " screenCoords.x: " << screenCoords.x << " screenCoords.y: " << screenCoords.y << std::endl;
std::cout << " bufferInd.x: " << xInd << " bufferInd.y: " << yInd << std::endl;
std::cout << " worldRay: ";
polyscope::operator<<(std::cout, worldRay) << std::endl;
std::cout << " worldPos: ";
Expand Down
4 changes: 3 additions & 1 deletion include/polyscope/pick.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ size_t requestPickBufferRange(Structure* requestingStructure, size_t count);
// == Main query
// Get the structure which was clicked on (nullptr if none), and the pick ID in local indices for that structure (such
// that 0 is the first index as returned from requestPickBufferRange())
std::pair<Structure*, size_t> evaluatePickQuery(int xPos, int yPos);
std::pair<Structure*, size_t> pickAtScreenCoords(glm::vec2 screenCoords); // takes screen coordinates
std::pair<Structure*, size_t> pickAtBufferCoords(int xPos, int yPos); // takes indices into the buffer
std::pair<Structure*, size_t> evaluatePickQuery(int xPos, int yPos); // old, badly named. takes buffer coordinates.


// == Stateful picking: track and update a current selection
Expand Down
4 changes: 3 additions & 1 deletion include/polyscope/view.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include <array>
#include <string>
#include <tuple>

#include "polyscope/camera_parameters.h"
#include "polyscope/types.h"
Expand Down Expand Up @@ -111,7 +112,7 @@ void getCameraFrame(glm::vec3& lookDir, glm::vec3& upDir, glm::vec3& rightDir);

// Get world geometry corresponding to a screen pixel (e.g. from a mouse click)
glm::vec3 screenCoordsToWorldRay(glm::vec2 screenCoords);
glm::vec3 bufferCoordsToWorldRay(glm::vec2 screenCoords);
glm::vec3 bufferCoordsToWorldRay(int xPos, int yPos);
glm::vec3 screenCoordsToWorldPosition(glm::vec2 screenCoords); // queries the depth buffer to get full position

// Flight-related
Expand All @@ -129,6 +130,7 @@ void setCameraFromJson(std::string jsonData, bool flyTo);
// Other helpers
std::string to_string(ProjectionMode mode);
std::string to_string(NavigateStyle style);
std::tuple<int, int> screenCoordsToBufferInds(glm::vec2 screenCoords);

// Internal helpers. Should probably not be called in user code.
void buildViewGui();
Expand Down
7 changes: 7 additions & 0 deletions src/pick.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,13 @@ size_t localIndexToGlobal(std::pair<Structure*, size_t> localPick) {
return rangeStart + localPick.second;
}

std::pair<Structure*, size_t> pickAtScreenCoords(glm::vec2 screenCoords) {
int xInd, yInd;
std::tie(xInd, yInd) = view::screenCoordsToBufferInds(screenCoords);
return pickAtBufferCoords(xInd, yInd);
}

std::pair<Structure*, size_t> pickAtBufferCoords(int xPos, int yPos) { return evaluatePickQuery(xPos, yPos); }

std::pair<Structure*, size_t> evaluatePickQuery(int xPos, int yPos) {

Expand Down
3 changes: 1 addition & 2 deletions src/polyscope.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -376,8 +376,7 @@ void processInputEvents() {
// Don't pick at the end of a long drag
if (dragDistSinceLastRelease < dragIgnoreThreshold) {
ImVec2 p = ImGui::GetMousePos();
std::pair<Structure*, size_t> pickResult =
pick::evaluatePickQuery(io.DisplayFramebufferScale.x * p.x, io.DisplayFramebufferScale.y * p.y);
std::pair<Structure*, size_t> pickResult = pick::pickAtScreenCoords(glm::vec2{p.x, p.y});
pick::setSelection(pickResult);
}

Expand Down
3 changes: 1 addition & 2 deletions src/surface_mesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1392,8 +1392,7 @@ long long int SurfaceMesh::selectVertex() {
// API is a giant mess..
size_t pickInd;
ImVec2 p = ImGui::GetMousePos();
std::pair<Structure*, size_t> pickVal =
pick::evaluatePickQuery(io.DisplayFramebufferScale.x * p.x, io.DisplayFramebufferScale.y * p.y);
std::pair<Structure*, size_t> pickVal = pick::pickAtScreenCoords(glm::vec2{p.x, p.y});

if (pickVal.first == this) {

Expand Down
24 changes: 18 additions & 6 deletions src/view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,19 @@ std::string to_string(NavigateStyle style) {
return ""; // unreachable
}


std::tuple<int, int> screenCoordsToBufferInds(glm::vec2 screenCoords) {

int xPos = (screenCoords.x * view::bufferWidth) / view::windowWidth;
int yPos = (screenCoords.y * view::bufferHeight) / view::windowHeight;

// clamp to lie in [0,width),[0,height)
xPos = std::max(std::min(xPos, view::bufferWidth - 1), 0);
yPos = std::max(std::min(yPos, view::bufferHeight - 1), 0);

return std::tuple<int, int>(xPos, yPos);
}

void processRotate(glm::vec2 startP, glm::vec2 endP) {

if (startP == endP) {
Expand Down Expand Up @@ -489,13 +502,13 @@ glm::vec3 screenCoordsToWorldRay(glm::vec2 screenCoords) {
return worldRayDir;
}

glm::vec3 bufferCoordsToWorldRay(glm::vec2 screenCoords) {
glm::vec3 bufferCoordsToWorldRay(glm::vec2 bufferCoords) {

glm::mat4 view = getCameraViewMatrix();
glm::mat4 proj = getCameraPerspectiveMatrix();
glm::vec4 viewport = {0., 0., view::bufferWidth, view::bufferHeight};

glm::vec3 screenPos3{screenCoords.x, view::bufferHeight - screenCoords.y, 0.};
glm::vec3 screenPos3{bufferCoords.x, view::bufferHeight - bufferCoords.y, 0.};
glm::vec3 worldPos = glm::unProject(screenPos3, view, proj, viewport);
glm::vec3 worldRayDir = glm::normalize(glm::vec3(worldPos) - getCameraWorldPosition());

Expand All @@ -505,9 +518,8 @@ glm::vec3 bufferCoordsToWorldRay(glm::vec2 screenCoords) {

glm::vec3 screenCoordsToWorldPosition(glm::vec2 screenCoords) {

glm::vec2 bufferCoords{screenCoords.x * static_cast<float>(view::bufferWidth) / static_cast<float>(view::windowWidth),
screenCoords.y * static_cast<float>(view::bufferHeight) /
static_cast<float>(view::windowHeight)};
int xInd, yInd;
std::tie(xInd, yInd) = screenCoordsToBufferInds(screenCoords);

glm::mat4 view = getCameraViewMatrix();
glm::mat4 viewInv = glm::inverse(view);
Expand All @@ -517,7 +529,7 @@ glm::vec3 screenCoordsToWorldPosition(glm::vec2 screenCoords) {

// query the depth buffer to get depth
render::FrameBuffer* sceneFramebuffer = render::engine->sceneBuffer.get();
float depth = sceneFramebuffer->readDepth(bufferCoords.x, view::bufferHeight - bufferCoords.y);
float depth = sceneFramebuffer->readDepth(xInd, view::bufferHeight - yInd);
if (depth == 1.) {
// if we didn't hit anything in the depth buffer, just return infinity
float inf = std::numeric_limits<float>::infinity();
Expand Down

0 comments on commit 45c86fc

Please sign in to comment.