Skip to content

Commit

Permalink
Merge pull request #1285 from miyanyan/fix-scale
Browse files Browse the repository at this point in the history
[fix] wrong scale value
  • Loading branch information
zhouhang95 authored Aug 29, 2023
2 parents aa8b23c + 9001840 commit f08217e
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 43 deletions.
25 changes: 15 additions & 10 deletions ui/zenoedit/viewport/cameracontrol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ void CameraControl::fakeMousePressEvent(QMouseEvent *event)
}
}
if (event->buttons() & Qt::MiddleButton) {
m_lastPos = event->pos();
m_lastMidButtonPos = event->pos();
} else if (event->buttons() & Qt::LeftButton) {
m_boundRectStartPos = event->pos();
// check if clicked a selected object
Expand Down Expand Up @@ -266,11 +266,11 @@ void CameraControl::fakeMouseMoveEvent(QMouseEvent *event)
{
auto session = m_zenovis->getSession();
auto scene = session->get_scene();
float xpos = event->x(), ypos = event->y();

if (event->buttons() & Qt::MiddleButton) {
float ratio = QApplication::desktop()->devicePixelRatio();
float xpos = event->x(), ypos = event->y();
float dx = xpos - m_lastPos.x(), dy = ypos - m_lastPos.y();
float dx = xpos - m_lastMidButtonPos.x(), dy = ypos - m_lastMidButtonPos.y();
dx *= ratio / m_res[0];
dy *= ratio / m_res[1];
bool shift_pressed = event->modifiers() & Qt::ShiftModifier;
Expand All @@ -295,20 +295,25 @@ void CameraControl::fakeMouseMoveEvent(QMouseEvent *event)
setTheta(getTheta() - dy * M_PI);
setPhi(getPhi() + dx * M_PI);
}
m_lastPos = QPointF(xpos, ypos);
m_lastMidButtonPos = QPointF(xpos, ypos);
} else if (event->buttons() & Qt::LeftButton) {
if (m_transformer)
{
if (m_transformer->isTransforming()) {
auto dir = screenToWorldRay(event->pos().x() / res().x(), event->pos().y() / res().y());
auto camera_pos = realPos();
auto x = event->x() * 1.0f;
auto y = event->y() * 1.0f;
x = (2 * x / res().x()) - 1;
y = 1 - (2 * y / res().y());
auto mouse_pos = glm::vec2(x, y);

// mouse pos
auto mouse_pos = glm::vec2(xpos, ypos);
mouse_pos[0] = (2 * mouse_pos[0] / res().x()) - 1;
mouse_pos[1] = 1 - (2 * mouse_pos[1] / res().y());
// mouse start
auto mouse_start = glm::vec2(m_boundRectStartPos.x(), m_boundRectStartPos.y());
mouse_start[0] = (2 * mouse_start[0] / res().x()) - 1;
mouse_start[1] = 1 - (2 * mouse_start[1] / res().y());

auto vp = scene->camera->m_proj * scene->camera->m_view;
m_transformer->transform(camera_pos, mouse_pos, dir, scene->camera->m_lodfront, vp);
m_transformer->transform(camera_pos, dir, mouse_start, mouse_pos, scene->camera->m_lodfront, vp);
zenoApp->getMainWindow()->updateViewport();
} else {
float min_x = std::min((float)m_boundRectStartPos.x(), (float)event->x()) / m_res.x();
Expand Down
2 changes: 1 addition & 1 deletion ui/zenoedit/viewport/cameracontrol.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class CameraControl : public QObject
void resizeTransformHandler(int dir);

private:
QPointF m_lastPos;
QPointF m_lastMidButtonPos;
QPoint m_boundRectStartPos;
QVector2D m_res;
QSet<int> m_pressedKeys;
Expand Down
16 changes: 12 additions & 4 deletions ui/zenoedit/viewportinteraction/transform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ bool FakeTransformer::clickedAnyHandler(QVector3D ori, QVector3D dir, glm::vec3
return m_operation_mode != zenovis::INTERACT_NONE;
}

void FakeTransformer::transform(QVector3D camera_pos, glm::vec2 mouse_pos, QVector3D ray_dir, glm::vec3 front, glm::mat4 vp) {
void FakeTransformer::transform(QVector3D camera_pos, QVector3D ray_dir, glm::vec2 mouse_start, glm::vec2 mouse_pos, glm::vec3 front, glm::mat4 vp) {
if (m_operation == NONE) return;

auto pZenovis = m_viewport->getZenoVis();
Expand Down Expand Up @@ -256,9 +256,17 @@ void FakeTransformer::transform(QVector3D camera_pos, glm::vec2 mouse_pos, QVect
}
}
else if (m_operation == SCALE) {
// make a circle, center is m_objects_center
// when mouse press, get the circle's radius, r = len(m_objects_center - mouse_start)
// when mouse move, get the len from center to mouse_pos, d = len(m_objects_center - mouse_pos)
// so the scale is d / r
auto t_ctr = vp * glm::vec4(m_objects_center, 1.0f);
glm::vec2 ctr = t_ctr / t_ctr[3];
auto scale_size = glm::length(ctr - mouse_pos);
auto len_ctr_start = glm::length(ctr - mouse_start);
if (len_ctr_start < 0.001) return;

auto len_ctr_pos = glm::length(ctr - mouse_pos);
auto scale_size = len_ctr_pos / len_ctr_start;
if (m_operation_mode == zenovis::INTERACT_X) {
scale(scale_size, {1, 0, 0});
}
Expand Down Expand Up @@ -635,8 +643,8 @@ void FakeTransformer::translate(glm::vec3 start, glm::vec3 end, glm::vec3 axis)

void FakeTransformer::scale(float scale_size, vec3i axis) {
glm::vec3 scale(1.0f);
for (int i=0; i<3; i++)
if (axis[i] == 1) scale[i] = fmax(scale_size * 3, 0.1);
for (int i = 0; i < 3; i++)
if (axis[i] == 1) scale[i] = std::max(scale_size, 0.1f);
m_scale = scale;
doTransform();
}
Expand Down
2 changes: 1 addition & 1 deletion ui/zenoedit/viewportinteraction/transform.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class FakeTransformer {
void removeObject(const std::unordered_set<std::string>& names);
bool calcTransformStart(glm::vec3 ori, glm::vec3 dir, glm::vec3 front);
bool clickedAnyHandler(QVector3D ori, QVector3D dir, glm::vec3 front);
void transform(QVector3D camera_pos, glm::vec2 mouse_pos, QVector3D ray_dir, glm::vec3 front, glm::mat4 vp);
void transform(QVector3D camera_pos, QVector3D ray_dir, glm::vec2 mouse_start, glm::vec2 mouse_pos, glm::vec3 front, glm::mat4 vp);
void startTransform();
void endTransform(bool moved);
bool isTransforming() const;
Expand Down
37 changes: 34 additions & 3 deletions zenovis/include/zenovis/bate/GraphicHandlerUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,11 @@ void drawSquare(vec3f pos, vec3f a, vec3f b, vec3f color, float size, std::uniqu
}

void drawCircle(vec3f pos, vec3f a, vec3f b, vec3f color, float size, std::unique_ptr<Buffer> &vbo) {
constexpr int point_num = 100;
constexpr double step = 1.0 / point_num;
std::vector<vec3f> mem;
mem.reserve(point_num * 2);

double point_num = 100;
double step = 1.0 / point_num;
for (double t = 0; t < 1.0; t += step) {
double theta = 2.0 * PI * t;
auto p = pos + size * cos(theta) * a + size * sin(theta) * b;
Expand All @@ -133,13 +134,43 @@ void drawCircle(vec3f pos, vec3f a, vec3f b, vec3f color, float size, std::uniqu
vbo->attribute(0, sizeof(float) * 0, sizeof(float) * 6, GL_FLOAT, 3);
vbo->attribute(1, sizeof(float) * 3, sizeof(float) * 6, GL_FLOAT, 3);

CHECK_GL(glDrawArrays(GL_LINE_STRIP, 0, vertex_count));
CHECK_GL(glDrawArrays(GL_LINE_LOOP, 0, vertex_count));

vbo->disable_attribute(0);
vbo->disable_attribute(1);
vbo->unbind();
}

void drawCircle(vec3f pos, vec3f a, vec3f b, vec3f color, float size, float width, std::unique_ptr<Buffer> &vbo) {
constexpr int point_num = 100;
constexpr double step = 1.0 / point_num;
std::vector<vec3f> mem;
mem.reserve(point_num * 4);

float inner_size = size - width / 2.0;
float outer_size = size + width / 2.0;
for (double t = 0; t < 1.0 + step; t += step) {
double theta = 2.0 * PI * t;
auto p1 = pos + inner_size * cos(theta) * a + inner_size * sin(theta) * b;
auto p2 = pos + outer_size * cos(theta) * a + outer_size * sin(theta) * b;
mem.push_back(p1);
mem.push_back(color);
mem.push_back(p2);
mem.push_back(color);
}

auto vertex_count = mem.size() / 2;
vbo->bind_data(mem.data(), mem.size() * sizeof(mem[0]));

vbo->attribute(0, sizeof(float) * 0, sizeof(float) * 6, GL_FLOAT, 3);
vbo->attribute(1, sizeof(float) * 3, sizeof(float) * 6, GL_FLOAT, 3);

CHECK_GL(glDrawArrays(GL_TRIANGLE_STRIP, 0, vertex_count));

vbo->disable_attribute(0);
vbo->disable_attribute(1);
vbo->unbind();
}

void drawCube(vec3f pos, vec3f a, vec3f b, vec3f color, float size, std::unique_ptr<Buffer> &vbo) {
std::vector<vec3f> mem;
Expand Down
78 changes: 54 additions & 24 deletions zenovis/src/bate/GraphicScaleHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@ struct ScaleHandler final : IGraphicHandler {
std::unique_ptr<Buffer> lines_ebo;
size_t lines_count;

static constexpr float cube_factor = 0.08f;
static constexpr float axis_factor = 0.8f;
static constexpr float square_factor = 0.1f;
static constexpr float icircle_factor = 0.2f; // inner circle
static constexpr float ocircle_factor = 1.0f; // outer circle

explicit ScaleHandler(Scene *scene_, vec3f &center_, float scale_)
: scene(scene_), center(center_), scale(scale_), mode(INTERACT_NONE) {
vbo = std::make_unique<Buffer>(GL_ARRAY_BUFFER);
Expand All @@ -97,53 +103,64 @@ struct ScaleHandler final : IGraphicHandler {
auto y_axis = vec3f(0, 1, 0);
auto z_axis = vec3f(0, 0, 1);

auto axis_size = bound * axis_factor;
auto cube_size = bound * cube_factor;
auto square_size = bound * square_factor;
auto icircle_size = bound * icircle_factor;
auto ocircle_size = bound * ocircle_factor;

// x axis
if (mode == INTERACT_NONE || mode == INTERACT_X) {
drawAxis(center, x_axis, r, bound, vbo);
drawCube(center + bound * x_axis, y_axis, z_axis, r, bound * 0.08f, vbo);
drawAxis(center, x_axis, r, axis_size, vbo);
drawCube(center + axis_size * x_axis, y_axis, z_axis, r, cube_size, vbo);
}

if (mode == INTERACT_NONE || mode == INTERACT_Y) {
drawAxis(center, y_axis, g, bound, vbo);
drawCube(center + bound * y_axis, z_axis, x_axis, g, bound * 0.08f, vbo);
drawAxis(center, y_axis, g, axis_size, vbo);
drawCube(center + axis_size * y_axis, z_axis, x_axis, g, cube_size, vbo);
}

if (mode == INTERACT_NONE || mode == INTERACT_Z) {
drawAxis(center, z_axis, b, bound, vbo);
drawCube(center + bound * z_axis, x_axis, y_axis, b, bound * 0.08f, vbo);
drawAxis(center, z_axis, b, axis_size, vbo);
drawCube(center + axis_size * z_axis, x_axis, y_axis, b, cube_size, vbo);
}

if (mode == INTERACT_NONE || mode == INTERACT_YZ)
drawSquare(center, y_axis, z_axis, {0.6, 0.2, 0.2}, bound * 0.1f, vbo);
drawSquare(center, y_axis, z_axis, {0.6, 0.2, 0.2}, square_size, vbo);

if (mode == INTERACT_NONE || mode == INTERACT_XZ)
drawSquare(center, z_axis, x_axis, {0.2, 0.6, 0.2}, bound * 0.1f, vbo);
drawSquare(center, z_axis, x_axis, {0.2, 0.6, 0.2}, square_size, vbo);

if (mode == INTERACT_NONE || mode == INTERACT_XY)
drawSquare(center, x_axis, y_axis, {0.2, 0.2, 0.6}, bound * 0.1f, vbo);

if (mode == INTERACT_NONE || mode == INTERACT_XYZ)
drawCube(center, y_axis, z_axis, {0.51, 0.17, 0.85}, bound * 0.08f, vbo);
drawSquare(center, x_axis, y_axis, {0.2, 0.2, 0.6}, square_size, vbo);

const auto& view = scene->camera->m_view;
if (mode == INTERACT_NONE || mode == INTERACT_XYZ) {
// http://www.opengl-tutorial.org/cn/intermediate-tutorials/billboards-particles/billboards/
// always face camera
// This is equivalent to mlutiplying (1,0,0) and (0,1,0) by inverse(ViewMatrix).
// ViewMatrix is orthogonal (it was made this way),
// so its inverse is also its transpose,
// and transposing a matrix is "free" (inversing is slooow)
auto right_world = vec3f(view[0][0], view[1][0], view[2][0]);
auto up_world = vec3f(view[0][1], view[1][1], view[2][1]);
drawCircle(center, right_world, up_world, { 1.0, 1.0, 1.0 }, icircle_size, bound * 0.01f, vbo);
drawCircle(center, right_world, up_world, { 1.0, 1.0, 1.0 }, ocircle_size, bound * 0.01f, vbo);
}
}

virtual int collisionTest(glm::vec3 ori, glm::vec3 dir) override {
auto x_axis = glm::vec3(1, 0, 0);
auto y_axis = glm::vec3(0, 1, 0);
auto z_axis = glm::vec3(0, 0, 1);

auto model_matrix =glm::translate(zeno::vec_to_other<glm::vec3>(center));

// xyz handler
float cube_size = bound * 0.08f; float t;
auto xyz_handler_max = cube_size * glm::vec3(1.0f);
auto xyz_handler_min = -xyz_handler_max;
if (rayIntersectOBB(ori, dir, xyz_handler_min, xyz_handler_max, model_matrix, t)) {
mode = INTERACT_XYZ;
return INTERACT_XYZ;
}
auto model_matrix = glm::translate(zeno::vec_to_other<glm::vec3>(center));
const auto& view = scene->camera->m_view;

float t;

// axis handlers
float axis_handler_l = bound * 1.1f;
float axis_handler_l = bound * axis_factor;
float axis_handler_w = bound * 0.1f;

// x handler
Expand Down Expand Up @@ -172,7 +189,7 @@ struct ScaleHandler final : IGraphicHandler {

// plane handlers
float square_ctr_offset = bound;
float square_size = bound * 0.1f;
float square_size = bound * square_factor;

// xy handler
auto xy_base = glm::normalize(x_axis + y_axis);
Expand Down Expand Up @@ -201,6 +218,19 @@ struct ScaleHandler final : IGraphicHandler {
return INTERACT_XZ;
}

// xyz handler
// the other handlers are in the range of xyz handler, so check xyz at last
float i_radius = bound * icircle_factor;
float o_radius = bound * ocircle_factor;
float thickness = bound * 0.1f;
auto right_world = vec3f(view[0][0], view[1][0], view[2][0]);
auto up_world = vec3f(view[0][1], view[1][1], view[2][1]);
if (rayIntersectRing(ori, dir, glm::vec3(0), o_radius, i_radius, zeno::vec_to_other<glm::vec3>(right_world),
zeno::vec_to_other<glm::vec3>(up_world), thickness, model_matrix)) {
mode = INTERACT_XYZ;
return INTERACT_XYZ;
}

mode = INTERACT_NONE;
return INTERACT_NONE;
}
Expand Down

0 comments on commit f08217e

Please sign in to comment.