Skip to content

Commit

Permalink
Fix and Improve trackball interactivity
Browse files Browse the repository at this point in the history
- Fixed bug in trackball computation that was incorrectly using angle
  in degrees instead of radians
- Add custom Cursors for zoom and rotation modes to visually aid the
  user
  - Hand cursor appears when rotation is activated(Mouse Right button
    drag)
  - Arrow with top and bottom heads is activated when zoom in/out mode
    is active(Ctrl + Left Right button) to hint the required cursor
    movement for desired zoom in or zoom out

SDL window toolkit additionally has custom move cursor.

(cherry picked from commit dc54597)
  • Loading branch information
9prady9 committed Apr 28, 2021
1 parent 7e02678 commit 3803106
Showing 22 changed files with 422 additions and 225 deletions.
15 changes: 10 additions & 5 deletions src/backend/common/defines.hpp
Original file line number Diff line number Diff line change
@@ -20,11 +20,16 @@ namespace common {
using CellIndex = std::tuple<int, int, int>;
using MatrixHashMap = std::unordered_map<CellIndex, glm::mat4>;

constexpr float PI = 3.14159f;
constexpr float BLACK[] = {0.0f, 0.0f, 0.0f, 1.0f};
constexpr float GRAY[] = {0.75f, 0.75f, 0.75f, 1.0f};
constexpr float WHITE[] = {1.0f, 1.0f, 1.0f, 1.0f};
constexpr float AF_BLUE[] = {0.0588f, 0.1137f, 0.2745f, 1.0f};
constexpr int ARCBALL_CIRCLE_POINTS = 100;
constexpr float MOVE_SPEED = 0.005f;
constexpr float ZOOM_SPEED = 0.0075f;
constexpr float EPSILON = 1.0e-6f;
constexpr float ARC_BALL_RADIUS = 0.75f;
constexpr double PI = 3.14159265358979323846;
constexpr float BLACK[] = {0.0f, 0.0f, 0.0f, 1.0f};
constexpr float GRAY[] = {0.75f, 0.75f, 0.75f, 1.0f};
constexpr float WHITE[] = {1.0f, 1.0f, 1.0f, 1.0f};
constexpr float AF_BLUE[] = {0.0588f, 0.1137f, 0.2745f, 1.0f};
static const glm::mat4 IDENTITY(1.0f);

#if defined(OS_WIN)
45 changes: 31 additions & 14 deletions src/backend/common/util.cpp
Original file line number Diff line number Diff line change
@@ -20,6 +20,11 @@
#include <Windows.h>
#endif

using glm::vec2;
using glm::vec3;
using glm::vec4;
using std::make_pair;
using std::pair;
using std::string;

namespace forge {
@@ -142,20 +147,32 @@ std::ostream& operator<<(std::ostream& pOut, const glm::mat4& pMat) {
return pOut;
}

glm::vec3 trackballPoint(const float pX, const float pY, const float pWidth,
const float pHeight) {
glm::vec3 P =
glm::vec3(1.0 * pX / pWidth * 2 - 1.0, 1.0 * pY / pHeight * 2 - 1.0, 0);

P.y = -P.y;
float OP_squared = P.x * P.x + P.y * P.y;
if (OP_squared <= 1 * 1) {
P.z = sqrt(1 * 1 - OP_squared);
} else {
P.z = 0;
P = glm::normalize(P);
}
return P;
pair<vec3, float> calcRotationFromArcBall(const vec2& lastPos,
const vec2& currPos,
const vec4& viewport) {
auto project = [](const float pX, const float pY, const float pWidth,
const float pHeight) {
glm::vec3 P = glm::vec3((2.0f * pX) / pWidth - 1.0f,
(2.0f * pY) / pHeight - 1.0f, 0.0f);
float xySqrdSum = P.x * P.x + P.y * P.y;
float rSqrd = (ARC_BALL_RADIUS * ARC_BALL_RADIUS);
float rSqrdBy2 = rSqrd / 2.0f;
// Project to Hyperbolic Sheet if Sum of X^2 and Y^2 is
// greater than (RADIUS^2)/2 ; Otherwise to a sphere
P.z = (xySqrdSum > rSqrdBy2 ? rSqrdBy2 / sqrt(xySqrdSum)
: sqrt(rSqrd - xySqrdSum));
return P;
};
auto ORG = vec2(viewport[0], viewport[1]);
// Offset window position to viewport frame of reference
auto p1 = lastPos - ORG;
auto p2 = currPos - ORG;
auto op1 = project(p1.x, p1.y, viewport[2], viewport[3]);
auto op2 = project(p2.x, p2.y, viewport[2], viewport[3]);
auto n1 = glm::normalize(op1);
auto n2 = glm::normalize(op2);

return make_pair(glm::cross(op2, op1), std::acos(glm::dot(n1, n2)));
}

} // namespace common
17 changes: 14 additions & 3 deletions src/backend/common/util.hpp
Original file line number Diff line number Diff line change
@@ -16,6 +16,7 @@

#include <iostream>
#include <string>
#include <utility>
#include <vector>

namespace forge {
@@ -54,9 +55,19 @@ std::string toString(const float pVal, const std::string pFormat);
/* Print glm::mat4 to std::cout stream */
std::ostream& operator<<(std::ostream&, const glm::mat4&);

/* get the point of the surface of track ball */
glm::vec3 trackballPoint(const float pX, const float pY, const float pWidth,
const float pHeight);
/* Calculate rotation axis and amount of rotation of Arc Ball
*
* This computation requires previous and current mouse cursor positions
* which are the input parameters to this function call
*
* @lastPos previous mouse position
* @currPos current mouse position
*
* @return Rotation axis vector and the angle of rotation
* */
std::pair<glm::vec3, float> calcRotationFromArcBall(const glm::vec2& lastPos,
const glm::vec2& currPos,
const glm::vec4& viewport);

} // namespace common
} // namespace forge
34 changes: 18 additions & 16 deletions src/backend/glsl_shaders/plot3_fs.glsl
Original file line number Diff line number Diff line change
@@ -3,31 +3,33 @@
uniform vec2 minmaxs[3];
uniform bool isPVCOn;
uniform bool isPVAOn;
uniform bool isAssistDraw;
uniform vec4 lineColor;

in vec4 hpoint;
in vec4 pervcol;

out vec4 outColor;

vec3 hsv2rgb(vec3 c)
{
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
vec3 hsv2rgb(vec3 c) {
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}

void main(void)
{
bool nin_bounds = (hpoint.x > minmaxs[0].y || hpoint.x < minmaxs[0].x
|| hpoint.y > minmaxs[1].y || hpoint.y < minmaxs[1].x
|| hpoint.z < minmaxs[2].x);
void main(void) {
bool nin_bounds = (hpoint.x > minmaxs[0].y || hpoint.x < minmaxs[0].x ||
hpoint.y > minmaxs[1].y || hpoint.y < minmaxs[1].x ||
hpoint.z < minmaxs[2].x);

float height = (minmaxs[2].y- hpoint.z)/(minmaxs[2].y-minmaxs[2].x);
float height = (minmaxs[2].y - hpoint.z) / (minmaxs[2].y - minmaxs[2].x);

float a = isPVAOn ? pervcol.w : 1.0;
float a = isPVAOn ? pervcol.w : 1.0;

if(nin_bounds)
discard;
else
outColor = isPVCOn ? vec4(pervcol.xyz, a) : vec4(hsv2rgb(vec3(height, 1, 1)),a);
if (nin_bounds)
discard;
else
outColor = isPVCOn ? vec4(pervcol.xyz, a)
: isAssistDraw ? lineColor
: vec4(hsv2rgb(vec3(height, 1, 1)), a);
}
14 changes: 13 additions & 1 deletion src/backend/opengl/abstract_renderable.hpp
Original file line number Diff line number Diff line change
@@ -36,6 +36,7 @@ class AbstractRenderable {
std::string mLegend;
bool mIsPVCOn;
bool mIsPVAOn;
bool mIsInternalObject;

AbstractRenderable()
: mVBO(0)
@@ -45,7 +46,8 @@ class AbstractRenderable {
, mCBOSize(0)
, mABOSize(0)
, mIsPVCOn(0)
, mIsPVAOn(0) {
, mIsPVAOn(0)
, mIsInternalObject(false) {
mColor[0] = 0;
mColor[1] = 0;
mColor[2] = 0;
@@ -147,6 +149,16 @@ class AbstractRenderable {
virtual void render(const int pWindowId, const int pX, const int pY,
const int pVPW, const int pVPH, const glm::mat4& pView,
const glm::mat4& pOrient) = 0;

/*
* Mark the renderable is for internal use for assistive help
*/
inline void markAsInternalObject() { mIsInternalObject = true; }

/*
* Only rotatble renderables need to show 3d dimenionsional helper objects
*/
virtual bool isRotatable() const = 0;
};

} // namespace opengl
4 changes: 4 additions & 0 deletions src/backend/opengl/chart_impl.hpp
Original file line number Diff line number Diff line change
@@ -168,6 +168,8 @@ class chart2d_impl : public AbstractChart {
void render(const int pWindowId, const int pX, const int pY, const int pVPW,
const int pVPH, const glm::mat4& pView,
const glm::mat4& pOrient);

bool isRotatable() const { return false; }
};

class chart3d_impl : public AbstractChart {
@@ -189,6 +191,8 @@ class chart3d_impl : public AbstractChart {
void render(const int pWindowId, const int pX, const int pY, const int pVPW,
const int pVPH, const glm::mat4& pView,
const glm::mat4& pOrient);

bool isRotatable() const { return true; }
};

} // namespace opengl
Loading

0 comments on commit 3803106

Please sign in to comment.