Skip to content

Commit

Permalink
Fix per grid rotation arcball hint in grid layout
Browse files Browse the repository at this point in the history
Viewport call was not suitable for grid layout rendering. Hence
implemented custom logic based on cursor position to figure out viewport
from it.

(cherry picked from commit b9b4a98)
  • Loading branch information
9prady9 committed Apr 28, 2021
1 parent 3803106 commit fe1c840
Show file tree
Hide file tree
Showing 6 changed files with 168 additions and 94 deletions.
1 change: 1 addition & 0 deletions src/backend/common/defines.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <common/util.hpp>

#include <unordered_map>
#include <utility>

namespace forge {
namespace common {
Expand Down
103 changes: 63 additions & 40 deletions src/backend/opengl/glfw/window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <glm/gtc/type_ptr.hpp>

#include <cmath>
#include <utility>

using glm::epsilonNotEqual;
using glm::make_vec4;
Expand All @@ -26,6 +27,11 @@ using glm::scale;
using glm::translate;
using glm::vec2;
using glm::vec3;
using glm::vec4;
using std::floor;
using std::get;
using std::make_tuple;
using std::tuple;

using namespace forge::common;

Expand All @@ -43,60 +49,74 @@ void initWindowToolkit() {

void destroyWindowToolkit() { glfwTerminate(); }

const mat4 Widget::findTransform(const MatrixHashMap& pMap, const float pX,
const float pY) {
tuple<vec3, vec2> getCellCoordsDims(const vec2& pos, const CellIndex& idx,
const vec2& dims) {
const int rows = get<0>(idx);
const int cols = get<1>(idx);
const int cw = dims[0] / cols;
const int ch = dims[1] / rows;
const int x = static_cast<int>(floor(pos[0] / static_cast<double>(cw)));
const int y = static_cast<int>(floor(pos[1] / static_cast<double>(ch)));
return make_tuple(vec3(x * cw, y * ch, x + y * cols), vec2(cw, ch));
}

const vec4 Widget::getCellViewport(const vec2& pos) {
// Either of the transformation matrix maps are fine for figuring
// out the viewport corresponding to the current mouse position
// Here I am using mOrientMatrices map
vec4 retVal(0, 0, mWidth, mHeight);
for (auto& it : mOrientMatrices) {
const CellIndex& idx = it.first;
auto coordsAndDims = getCellCoordsDims(pos, idx, vec2(mWidth, mHeight));
if (get<0>(coordsAndDims)[2] == std::get<2>(idx)) {
retVal = vec4(get<0>(coordsAndDims)[0], get<0>(coordsAndDims)[1],
get<1>(coordsAndDims));
break;
}
}
return retVal;
}

const mat4 Widget::findTransform(const MatrixHashMap& pMap, const double pX,
const double pY) {
for (auto it : pMap) {
const CellIndex& idx = it.first;
const mat4& mat = it.second;

const int rows = std::get<0>(idx);
const int cols = std::get<1>(idx);

const int cellWidth = mWidth / cols;
const int cellHeight = mHeight / rows;

const int x = int(pX) / cellWidth;
const int y = int(pY) / cellHeight;
const int i = x + y * cols;
if (i == std::get<2>(idx)) { return mat; }
auto coordsAndDims =
getCellCoordsDims(vec2(pX, pY), idx, vec2(mWidth, mHeight));
if (get<0>(coordsAndDims)[2] == std::get<2>(idx)) { return mat; }
}

return IDENTITY;
}

const mat4 Widget::getCellViewMatrix(const float pXPos, const float pYPos) {
const mat4 Widget::getCellViewMatrix(const double pXPos, const double pYPos) {
return findTransform(mViewMatrices, pXPos, pYPos);
}

const mat4 Widget::getCellOrientationMatrix(const float pXPos,
const float pYPos) {
const mat4 Widget::getCellOrientationMatrix(const double pXPos,
const double pYPos) {
return findTransform(mOrientMatrices, pXPos, pYPos);
}

void Widget::setTransform(MatrixHashMap& pMap, const float pX, const float pY,
void Widget::setTransform(MatrixHashMap& pMap, const double pX, const double pY,
const mat4& pMat) {
for (auto it : pMap) {
const CellIndex& idx = it.first;

const int rows = std::get<0>(idx);
const int cols = std::get<1>(idx);

const int cellWidth = mWidth / cols;
const int cellHeight = mHeight / rows;

const int x = int(pX) / cellWidth;
const int y = int(pY) / cellHeight;
const int i = x + y * cols;
if (i == std::get<2>(idx)) { pMap[idx] = pMat; }
auto coordsAndDims =
getCellCoordsDims(vec2(pX, pY), idx, vec2(mWidth, mHeight));
if (get<0>(coordsAndDims)[2] == std::get<2>(idx)) {
pMap[idx] = pMat;
return;
}
}
}

void Widget::setCellViewMatrix(const float pXPos, const float pYPos,
void Widget::setCellViewMatrix(const double pXPos, const double pYPos,
const mat4& pMatrix) {
return setTransform(mViewMatrices, pXPos, pYPos, pMatrix);
}

void Widget::setCellOrientationMatrix(const float pXPos, const float pYPos,
void Widget::setCellOrientationMatrix(const double pXPos, const double pYPos,
const mat4& pMatrix) {
return setTransform(mOrientMatrices, pXPos, pYPos, pMatrix);
}
Expand Down Expand Up @@ -169,7 +189,7 @@ Widget::Widget(int pWidth, int pHeight, const char* pTitle,

auto cursorCallback = [](GLFWwindow* w, double xpos, double ypos) {
static_cast<Widget*>(glfwGetWindowUserPointer(w))
->cursorHandler(float(xpos), float(ypos));
->cursorHandler(xpos, ypos);
};

auto mouseButtonCallback = [](GLFWwindow* w, int button, int action,
Expand Down Expand Up @@ -250,7 +270,7 @@ void Widget::keyboardHandler(int pKey, int pScancode, int pAction, int pMods) {
if (pKey == GLFW_KEY_ESCAPE && pAction == GLFW_PRESS) { hide(); }
}

void Widget::cursorHandler(const float pXPos, const float pYPos) {
void Widget::cursorHandler(const double pXPos, const double pYPos) {
constexpr auto ZOOM_ENABLER =
GLFW_MOUSE_BUTTON_LEFT + 10 * GLFW_MOD_CONTROL;

Expand All @@ -268,7 +288,7 @@ void Widget::cursorHandler(const float pXPos, const float pYPos) {
setCellViewMatrix(pXPos, pYPos, vMat);
} else if (mButton == ZOOM_ENABLER) {
// Zoom
float dy = delta[1];
double dy = delta[1];
if (!(std::abs(dy) < EPSILON)) {
if (dy < 0.0f) { dy = -1.0f / dy; }
mat4 vMat = scale(viewMat, vec3(pow(dy, ZOOM_SPEED)));
Expand All @@ -279,12 +299,9 @@ void Widget::cursorHandler(const float pXPos, const float pYPos) {
auto compCmp = epsilonNotEqual(mLastPos, currPos, vec2(EPSILON));
if (compCmp[0] || compCmp[1]) {
const mat4 oMat = getCellOrientationMatrix(pXPos, pYPos);

int view[4];
glGetIntegerv(GL_VIEWPORT, view);

const vec4 vprt = getCellViewport(currPos);
auto rotParams =
calcRotationFromArcBall(mLastPos, currPos, make_vec4(view));
calcRotationFromArcBall(mLastPos, currPos, vprt);

setCellOrientationMatrix(
pXPos, pYPos,
Expand All @@ -303,7 +320,7 @@ void Widget::mouseButtonHandler(int pButton, int pAction, int pMods) {

double x, y;
glfwGetCursorPos(mWindow, &x, &y);
auto pos = vec2(float(x), float(y));
auto pos = vec2(x, y);

if (mButtonAction == GLFW_PRESS) {
if (mButton == GLFW_MOUSE_BUTTON_RIGHT) {
Expand Down Expand Up @@ -345,5 +362,11 @@ const mat4 Widget::getOrientationMatrix(const CellIndex& pIndex) {
return mOrientMatrices[pIndex];
}

glm::vec2 Widget::getCursorPos() const {
double xp, yp;
glfwGetCursorPos(mWindow, &xp, &yp);
return {xp, yp};
}

} // namespace wtk
} // namespace forge
21 changes: 12 additions & 9 deletions src/backend/opengl/glfw/window.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,17 @@ class Widget {

Widget();

const glm::vec4 getCellViewport(const glm::vec2& pos);
const glm::mat4 findTransform(const forge::common::MatrixHashMap& pMap,
const float pX, const float pY);
const glm::mat4 getCellViewMatrix(const float pXPos, const float pYPos);
const glm::mat4 getCellOrientationMatrix(const float pXPos,
const float pYPos);
void setTransform(forge::common::MatrixHashMap& pMap, const float pX,
const float pY, const glm::mat4& pMat);
void setCellViewMatrix(const float pXPos, const float pYPos,
const double pX, const double pY);
const glm::mat4 getCellViewMatrix(const double pXPos, const double pYPos);
const glm::mat4 getCellOrientationMatrix(const double pXPos,
const double pYPos);
void setTransform(forge::common::MatrixHashMap& pMap, const double pX,
const double pY, const glm::mat4& pMat);
void setCellViewMatrix(const double pXPos, const double pYPos,
const glm::mat4& pMatrix);
void setCellOrientationMatrix(const float pXPos, const float pYPos,
void setCellOrientationMatrix(const double pXPos, const double pYPos,
const glm::mat4& pMatrix);

public:
Expand Down Expand Up @@ -95,7 +96,7 @@ class Widget {

void keyboardHandler(int pKey, int pScancode, int pAction, int pMods);

void cursorHandler(float pXPos, float pYPos);
void cursorHandler(double pXPos, double pYPos);

void mouseButtonHandler(int pButton, int pAction, int pMods);

Expand All @@ -108,6 +109,8 @@ class Widget {
void resetOrientationMatrices();

inline bool isBeingRotated() const { return mRotationFlag; }

glm::vec2 getCursorPos() const;
};

} // namespace wtk
Expand Down
97 changes: 60 additions & 37 deletions src/backend/opengl/sdl/window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ using glm::scale;
using glm::translate;
using glm::vec2;
using glm::vec3;
using glm::vec4;
using std::floor;
using std::get;
using std::make_tuple;
using std::tuple;

using namespace forge::common;

Expand All @@ -43,60 +48,74 @@ void initWindowToolkit() {

void destroyWindowToolkit() { SDL_Quit(); }

const mat4 Widget::findTransform(const MatrixHashMap& pMap, const float pX,
const float pY) {
tuple<vec3, vec2> getCellCoordsDims(const vec2& pos, const CellIndex& idx,
const vec2& dims) {
const int rows = get<0>(idx);
const int cols = get<1>(idx);
const int cw = dims[0] / cols;
const int ch = dims[1] / rows;
const int x = static_cast<int>(floor(pos[0] / static_cast<double>(cw)));
const int y = static_cast<int>(floor(pos[1] / static_cast<double>(ch)));
return make_tuple(vec3(x * cw, y * ch, x + y * cols), vec2(cw, ch));
}

const vec4 Widget::getCellViewport(const vec2& pos) {
// Either of the transformation matrix maps are fine for figuring
// out the viewport corresponding to the current mouse position
// Here I am using mOrientMatrices map
vec4 retVal(0, 0, mWidth, mHeight);
for (auto& it : mOrientMatrices) {
const CellIndex& idx = it.first;
auto coordsAndDims = getCellCoordsDims(pos, idx, vec2(mWidth, mHeight));
if (get<0>(coordsAndDims)[2] == std::get<2>(idx)) {
retVal = vec4(get<0>(coordsAndDims)[0], get<0>(coordsAndDims)[1],
get<1>(coordsAndDims));
break;
}
}
return retVal;
}

const mat4 Widget::findTransform(const MatrixHashMap& pMap, const double pX,
const double pY) {
for (auto it : pMap) {
const CellIndex& idx = it.first;
const mat4& mat = it.second;

const int rows = std::get<0>(idx);
const int cols = std::get<1>(idx);

const int cellWidth = mWidth / cols;
const int cellHeight = mHeight / rows;

const int x = int(pX) / cellWidth;
const int y = int(pY) / cellHeight;
const int i = x + y * cols;
if (i == std::get<2>(idx)) { return mat; }
auto coordsAndDims =
getCellCoordsDims(vec2(pX, pY), idx, vec2(mWidth, mHeight));
if (get<0>(coordsAndDims)[2] == std::get<2>(idx)) { return mat; }
}

return IDENTITY;
}

const mat4 Widget::getCellViewMatrix(const float pXPos, const float pYPos) {
const mat4 Widget::getCellViewMatrix(const double pXPos, const double pYPos) {
return findTransform(mViewMatrices, pXPos, pYPos);
}

const mat4 Widget::getCellOrientationMatrix(const float pXPos,
const float pYPos) {
const mat4 Widget::getCellOrientationMatrix(const double pXPos,
const double pYPos) {
return findTransform(mOrientMatrices, pXPos, pYPos);
}

void Widget::setTransform(MatrixHashMap& pMap, const float pX, const float pY,
void Widget::setTransform(MatrixHashMap& pMap, const double pX, const double pY,
const mat4& pMat) {
for (auto it : pMap) {
const CellIndex& idx = it.first;

const int rows = std::get<0>(idx);
const int cols = std::get<1>(idx);

const int cellWidth = mWidth / cols;
const int cellHeight = mHeight / rows;

const int x = int(pX) / cellWidth;
const int y = int(pY) / cellHeight;
const int i = x + y * cols;
if (i == std::get<2>(idx)) { pMap[idx] = pMat; }
auto coordsAndDims =
getCellCoordsDims(vec2(pX, pY), idx, vec2(mWidth, mHeight));
if (get<0>(coordsAndDims)[2] == std::get<2>(idx)) {
pMap[idx] = pMat;
return;
}
}
}

void Widget::setCellViewMatrix(const float pXPos, const float pYPos,
void Widget::setCellViewMatrix(const double pXPos, const double pYPos,
const mat4& pMatrix) {
return setTransform(mViewMatrices, pXPos, pYPos, pMatrix);
}

void Widget::setCellOrientationMatrix(const float pXPos, const float pYPos,
void Widget::setCellOrientationMatrix(const double pXPos, const double pYPos,
const mat4& pMatrix) {
return setTransform(mOrientMatrices, pXPos, pYPos, pMatrix);
}
Expand Down Expand Up @@ -265,7 +284,7 @@ void Widget::pollEvents() {
auto delta = mLastPos - currPos;
if (isCtrl) {
// Zoom
float dy = delta[1];
double dy = delta[1];
if (!(std::abs(dy) < EPSILON)) {
if (dy < 0.0f) { dy = -1.0 / dy; }
mat4 vMat =
Expand All @@ -286,11 +305,9 @@ void Widget::pollEvents() {
if (compCmp[0] || compCmp[1]) {
const mat4 oMat =
getCellOrientationMatrix(currPos[0], currPos[1]);
int view[4];
glGetIntegerv(GL_VIEWPORT, view);

auto rotParams = calcRotationFromArcBall(
mLastPos, currPos, make_vec4(view));
const vec4 vprt = getCellViewport(currPos);
auto rotParams =
calcRotationFromArcBall(mLastPos, currPos, vprt);

setCellOrientationMatrix(
currPos[0], currPos[1],
Expand Down Expand Up @@ -341,5 +358,11 @@ const mat4 Widget::getOrientationMatrix(const CellIndex& pIndex) {
return mOrientMatrices[pIndex];
}

glm::vec2 Widget::getCursorPos() const {
int xp, yp;
SDL_GetMouseState(&xp, &yp);
return {xp, yp};
}

} // namespace wtk
} // namespace forge
Loading

0 comments on commit fe1c840

Please sign in to comment.