【问题标题】:Why my drawings disappear after I release my left click?为什么我释放左键后我的绘图消失了?
【发布时间】:2019-11-06 23:43:14
【问题描述】:

所以我试图在 OpenGL 中在我单击的点之间画线。如果我按下左键,绘图会在屏幕上显示,但如果我松开左键,它就会消失:

struct Vector {
    float x, y;
    Vector(float x = 0, float y = 0) : x(x), y(y) {}

} last_mouse_pos;

void onInitialization() {
    glClearColor(0, 0, 0, 0); // A hatterszin beallitasa.
    glClear(GL_COLOR_BUFFER_BIT); // A kepernyo torlese, az uj hatterszinnel.
}

void onDisplay() {
    glutSwapBuffers();
}

Vector convertToNdc(float x, float y) {
    Vector ret;
    ret.x = (x - kScreenWidth / 2) / (kScreenWidth / 2);
    ret.y = (kScreenHeight / 2 - y) / (kScreenHeight / 2);
    return ret;
}

int i = 0;

void onMouse(int button, int state, int x, int y) {

    if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) {
        glClear(GL_COLOR_BUFFER_BIT); 
        glutPostRedisplay(); 
    }
    else if (button == GLUT_LEFT_BUTTON) {
        if (state == GLUT_DOWN) {
            i++;
            if (i == 1) last_mouse_pos = convertToNdc(x, y);
            if (i > 1) {
                Vector pos = convertToNdc(x, y);
                glBegin(GL_LINES);  
                glVertex2f(last_mouse_pos.x, last_mouse_pos.y);
                glVertex2f(pos.x, pos.y);
                glEnd();
                glutPostRedisplay();
                last_mouse_pos = pos; 
            }
        }
    }
}

所以我做了2点,如果我按住左键,它会画线,如果我松开它,屏幕会变黑。如果我点击其他地方,现在我有 2 行,但前提是我按下左键。如果我释放,它会再次变黑。

【问题讨论】:

  • 您可能收到了WM_ERASE 消息。
  • 您的绘图仅发生在鼠标按下代码中。OpenGL 中的缓冲区被交换(在您的情况下:glutSwapBuffers).. 您没有绘制每一帧,因此在下一帧时它会被擦除呈现。
  • 如果我已经换了...为什么又换回来了?
  • 不要在你的输入回调中绘制,锁定一些状态并通过glutPostRedisplay()请求重新调用你的显示回调并在那里绘制。

标签: c++ opengl glut


【解决方案1】:

是的,你的方法有很多错误。在几乎所有情况下,您的绘图函数都应该是数据驱动的(即数据控制绘制的内容,而只有数据!)。大致如下:

// use this vector to store all of the point clicks
std::vector<Vector> points;

void onDisplay() {

  // now just render each vertex making up the lines
  glBegin(GL_LINES);
  for(auto p : points)
    glVertex2f(p.x, p.y);
  glEnd();

  glutSwapBuffers();
}

接下来,您将需要跟踪鼠标的状态,因此为了尽可能简单(您可能还想跟踪鼠标位置和其他按钮状态,但是这是一个最小的例子)。

bool leftHeld = false;

接下来,您的鼠标功能现在将执行以下操作:

  1. 按下左键时,向点数组添加一个新顶点。
  2. 释放左键时,更新数组中最后一个点的位置
  3. 当按下右键(并且没有按下左键)时,清除点数组。
void onMouse(int button, int state, int x, int y) {
  switch(button) {
  case GLUT_LEFT_BUTTON:
    {
      leftHeld = state == GLUT_DOWN;
      if(leftHeld)
      {
        points.push_back(convertToNdc(x, y)); // add new point
      }
      else
        points.back() = convertToNdc(x, y); // update last point
    }
    break;

  // on right click, empty the array
  // (but only if the left mouse button isn't currently pressed!)
  case GLUT_RIGHT_BUTTON: 
    if(!leftHeld && state == GLUT_DOWN)
      points.clear();
    break;
  }
  glutPostRedisplay();
}

最后,如果您想在屏幕上单击并拖动时看到线条更新,您需要注册一个鼠标移动函数来更新数组中的最后一个点

// register with glutMotionFunc. 
// code updates last coordinate whilst mouse is moving, and
// the left button is held. 
void onMouseMove(int x, int y) {
  if(leftHeld)
  {
    points.back() = convertToNdc(x, y);
  }
  glutPostRedisplay();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-19
    • 2016-02-15
    相关资源
    最近更新 更多