如何在 OpenGL 中分别移动 2D 多个绘制的形状(正方形和矩形)?

How to move 2D multiple drawn shapes (Squares and Rectanagles) seperately in OpenGl?

提问人:Wiki 提问时间:12/9/2022 最后编辑:FareanorWiki 更新时间:8/26/2023 访问量:69

问:

我刚刚开始在 Visual Studio 中使用 OpenGl。

我使用 and 在单独的 void 函数中绘制多个形状,我在另一个名为 Display(void 返回类型)的函数中单独调用该函数,然后在 int main 中调用该函数来显示。drawsquare()drawRoundRect () glutDisplayFunc(Display)

在我使用的显示功能中,将 1 个形状的功能保持在两者之间,如下所示glutPushmatrix()glutPopMatrix ()

glutPushmatrix();
glutTranslatef(x,y,0); // z = 0 because i am making 2D shape
DrawSquare(50, 50, 50, colors[BALCK]); 
glutPopMatrix ();
glutPushmatrix();
glutTranslatef(x,y,0); // z = 0 because i am making 2D shape
DrawSquare(300, 300, 50, colors[BALCK]); 
glutPopMatrix ();

问题是,当我在屏幕上的任何位置(甚至不在形状上)单击鼠标时,这两个形状都开始一起移动。

Q1) 如何仅在点击并拖动鼠标时才逐个移动形状?

Q2) 我应该怎么做才能使形状仅在单击和拖动时移动,而当我单击屏幕上的其他任何位置时没有任何反应。

我使用了 和 函数,它们可以很好地移动一个形状,但我不知道如何仅在单击和拖动多个形状时才移动它们。glutPushMatrix()glutPopMatrix()glTranslatef ()

glutPushmatrix();
glutTranslatef(x,y,0); // z = 0 because i am making 2D shape
DrawSquare(50, 50, 50, colors[BALCK]); 
glutPopMatrix ();
glutPushmatrix();
glutTranslatef(x,y,0); // z = 0 because i am making 2D shape
DrawSquare(300, 300, 50, colors[BALCK]); 
glutPopMatrix ();

使用这段代码,我的两个图形一起移动,而不是分开移动。 此外,即使没有单击鼠标的任何形状,它们也会开始移动。

C++ 2D 游戏 OpenGL-3 OpenGL-4

评论

0赞 Head Wizard Locke 8/26/2023
我不确定为什么您在 OP 中重复了两次相同的代码

答:

0赞 Head Wizard Locke 8/26/2023 #1

您需要使用不同的位置值。由于您使用相同的 (x,y) 值(相同的变量),因此它们将以相同的速率沿同一方向移动,因为 (x,y) 是相同的位置。

// object 1
glutPushmatrix();
glutTranslatef(x1,y1,0); // x1,y1 is the position of object 1
DrawSquare(300, 300, 50, colors[BALCK]); 
glutPopMatrix ();
// object 2
glutPushmatrix();
glutTranslatef(x2,y2,0); // x2,y2 is the position of object 2
DrawSquare(300, 300, 50, colors[BALCK]); 
glutPopMatrix ();

但是,您可能需要一个包含对象并管理其数据的场景图。

对象应存储在场景图中,无论是 2D 还是 3D。2D 场景图基本上是按绘制顺序存储的对象数组。

例如,创建一个“实体”类,然后该类的一部分是坐标“位置”。结婚

class Entity { // a base class for objects
 public:
  double x,y,z,w,h;  // position, size
  int r,g,b;  // identifying color rgba 0-255, unique to each object
  Entity() { r=g=b=a=x=y=z=0.0; }
  virtual void Render() {
   // do your gl drawing here, push and pop
  }
  bool Within( double mx, double my ) { // return true if mx,my inside boundary
    return (mx > x && my > y && mx < x+w && my < y+h );
  }
  virtual void RenderOffscreenForPicking() { /* ... different for drawing for a different reason ... */ }
};

上面的示例将是一个“对象”,并且还应该包含您正在绘制的几何图形。它将包含一种识别颜色,用于渲染单个位置的单个对象。这样的对象可以使用多态性进行扩展。它可以包括速度、方向、旋转和许多其他值,以定义行为、绘图样式、几何图形等。

Q1) 如何仅在单击鼠标时逐个移动形状 并拖上具体形状?

Q2) 我应该怎么做才能使形状仅在单击时移动 并拖动,当我单击其他任何位置时没有任何反应 屏幕。

这两个问题的答案都需要使用一个称为“拣选”的概念 - 有许多不同的拣选方法。如果您的对象是“轴对齐边界框”(矩形),并且 x,y 值与屏幕坐标位于相同的范围/比例中,则可以使用简单的 AA 框测试(伪代码):

selected_object=null;
if ( mx > object1_x && my > object1_y
  && mx < object1_x+object1_width && my < object1_y+object1_height )
   selected_object=object1;

拾取的另一种方法是为每个对象分配颜色,在帧缓冲区(屏幕外缓冲区)上绘制对象。

  1. 首先,当用户 (mx,my) 首次在帧缓冲区上按下按钮时,使用“回读”测试鼠标位置,检查回读像素的颜色,然后使用它来确定单击了哪个对象。
  2. 单击时,在确定单击了哪个对象后,将所选对象保持在变量中,当鼠标移动时,通过鼠标增量(前一帧的鼠标位置与当前帧的鼠标位置之间的差值)移动对象,直到释放鼠标按钮。

这种方法的优点是对象的选择是“像素完美”的,不是由方框决定的,如果对象被遮挡(“在另一个对象后面”),你仍然可以拾取它。

旁注,如果您不熟悉使用 OpenGL,您可能希望避免使用 *f 函数并使用 *d 函数,例如代替 ,因为它们使用双精度,而不是浮点。glTranslated()glTranslatef()

评论

0赞 Head Wizard Locke 8/26/2023
请注意,github.com/LAGameStudio/apolune/blob/...是我在OpenGL游戏引擎中用于基本实体的类,它位于名为Proce55ors的场景图中。C++ 的多态特性允许我对此进行许多变化和优化,但这些是允许动画、响应鼠标事件、绘制、更新帧之间的值等的基类。