代码之家  ›  专栏  ›  技术社区  ›  Roel

在三维视图中实现操纵手柄的方法

  •  3
  • Roel  · 技术社区  · 15 年前

    我正在构建一个简单的实体建模应用程序。用户需要能够在正交视图和透视视图中操作对象。例如,当屏幕上有一个框,用户单击它来选择它时,它需要在角落和中心处获得“手柄”,以便用户可以将鼠标移动到这样的手柄上并拖动它来放大或移动框。

    有什么策略可以做到这一点,哪一个是最好的?我可以想到两个明显的例子:

    1)将控制柄视为三维对象。也就是说,对于一个盒子,在“主”盒子的角落添加小盒子到场景中。问题:这在透视视图中不起作用,我需要确定框相对于当前缩放级别的大小(不管用户放大/缩小到什么程度,句柄都需要具有相同的大小)。

    2)渲染场景后添加控制柄。渲染到屏幕外的缓冲区,以某种方式确定角的二维位置,并使用常规的二维绘制技术绘制控制柄。问题:我将如何进行HitTesting?我还需要进行两阶段的HitTesting方法;如何在3D渲染图像上绘制二维图像?回到GDI?

    这两种方法可能都存在更多的问题。有没有行业标准的方法来解决这个问题?

    我正在使用OpenGL,如果这有什么区别的话。

    4 回复  |  直到 13 年前
        1
  •  2
  •   Reed Copsey    15 年前

    我将把控制柄视为三维对象。这提供了许多优势——更稳定,它们表现良好,命中测试很容易,等等。

    如果希望控制柄的大小保持不变,则仍可以将其视为三维对象,但必须根据到相机的距离适当调整其大小。这有点麻烦,但由于通常只有几个句柄,而且这些句柄通常都是小对象,所以应该从性能上考虑。

    不过,我想说的是,让控制柄随场景缩放。只要为使其突出的控制柄选择一种渲染样式(例如:亮橙色框等),透视效果(背景中较小的控制柄)实际上在许多方面使最终用户更容易使用它们。很难从三维场景中获得深度感-控制柄上的透视效果有助于提供更多关于控制柄在屏幕中的“深度”的视觉线索。

        2
  •  1
  •   ParoXoN    15 年前

    首先,将控制柄/角坐标投影到相机平面上(有效地将它们转换为屏幕上的二维坐标;根据屏幕尺寸将其规范化)。

    下面是一些启用正交/2d覆盖绘图的简单代码:

    void enable2D()
    {
    
        glMatrixMode(GL_PROJECTION);
        glPushMatrix();
        glLoadIdentity();
        int wind[4];
        glGetIntegerv(GL_VIEWPORT,wind);
        glOrtho(0,wind[2],0,wind[3],-1,1);
        glMatrixMode(GL_MODELVIEW);
        glPushMatrix();
        glLoadIdentity();
    }
    
    
    void disable2D()
    {
        glMatrixMode(GL_PROJECTION);
        glPopMatrix();
        glMatrixMode(GL_MODELVIEW);
        glPopMatrix();
    }
    

    enable2d()缓存当前的模型视图/投影矩阵,并将投影矩阵替换为一个标准化到屏幕的矩阵(即屏幕的宽度/高度),并还原模型视图的标识矩阵。

    进行此调用后,可以使用屏幕/像素坐标进行glvertex2f()调用,允许您绘制二维!(这也允许您点击测试,因为您可以轻松获得鼠标当前的像素坐标。)

    完成后,调用disable2d恢复旧的模型视图/投影矩阵:)

    最困难的部分是计算打框落在二维平面上的位置,并处理重叠(如果两个项目位于同一位置,单击时选择哪个项目?)

    希望这有帮助:)

        3
  •  1
  •   tfinniga    15 年前

    我已经为一个3D编辑包编写了一个带有手柄的操纵器代码,并且遇到了很多相同的问题。

    首先,有一个开源操纵器。我在最近的搜索中找不到它,可能是因为这些东西的名称太多了——3D小部件、小发明、操纵器、万向节等等。

    不管怎样,我做的方法是在场景中添加一个操纵器对象,当绘制时,它会绘制所有的控制柄。它对边界框计算和选择执行相同的操作。

    Reed关于保持它们相同大小的想法对于存在于对象上并且可能在那里工作的句柄很有意思。对于一个操纵器,我发现它更多的是一个3dUI元素,如果它不改变大小的话,它就更有用了。我有一个bug,它的大小只根据活动的视区来确定,这导致了其他视区中可怕的巨大/微小的操纵器,非常无用。如果要将它们添加到场景中,您可能需要为每个视区添加它们,或者使它们实际具有固定的大小。

        4
  •  1
  •   davidnr    13 年前

    我知道这个问题很古老。但万一有人需要它:

    Interactive Techniques in Three-dimensional Scenes (Part 1): Moving 3D Objects with the Mouse using OpenGL 2.1

    文章不错,底部有一个有趣的链接部分。