【问题标题】:Ways to implement manipulation handles in 3d view在 3d 视图中实现操纵手柄的方法
【发布时间】:2009-05-06 14:10:23
【问题描述】:

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

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

1) 将手柄视为 3d 对象。 IE。对于一个盒子,将小盒子添加到“主”盒子角落的场景中。问题:这在透视图中不起作用,我需要确定相对于当前缩放级别的框的大小(无论用户放大/缩小多远,手柄都需要具有相同的大小)

2) 渲染场景后添加句柄。渲染到屏幕外缓冲区,以某种方式确定角的 2d 位置并使用常规 2d 绘图技术来绘制手柄。问题:我将如何进行命中测试?我还需要做一个两阶段的命中测试方法;如何在 3d 渲染图像上绘制 2d?回退到 GDI?

这两种方法可能存在更多问题。是否有解决此问题的行业标准方法?

我正在使用 OpenGL,如果这会有所不同的话。

【问题讨论】:

    标签: opengl 3d


    【解决方案1】:

    我会将手柄视为 3D 对象。这提供了许多优点 - 它更一致、它们表现良好、命中测试很容易等等。

    如果您希望手柄的大小保持不变,您仍然可以将它们视为 3D 对象,但您必须根据到相机的距离适当地缩放它们的大小。这有点麻烦,但由于通常只有几个句柄,而且这些通常是小对象,所以性能应该不错。

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

    【讨论】:

    • 我明白你关于透视添加视觉线索的观点。我还不相信这对用户来说会很自然。例如,被其他对象剪裁的句柄呢?我将检查其他一些 3d 建模器,看看他们是如何做到的,并在我的测试应用程序中尝试这两种方法。感谢您花时间回答。
    • 一种选择是让透视保持不变,但在关闭深度测试的情况下最后渲染它们。它们将始终可见(即使在其他对象之上)。我不会将其设为默认方式,但这是一个不错的选择,因此您可以打开/关闭是否始终显示句柄,甚至“通过”对象。
    • 我仍然需要了解它是如何与深度缓冲区一起工作的,但我认为这会奏效。我面前有很多试验和错误:) 谢谢。
    • 好吧,在这种情况下,您将关闭写入和测试深度缓冲区 - 基本上,它总是会绘制您的对象(在其他所有内容之上)。它不太直观,但作为切换/选项很有用。
    • 我们在我之前作为 3D 应用程序作者的化身中使用了这种方法,并且效果很好。不过我不会关闭深度测试。
    【解决方案2】:

    首先,将手柄/角坐标投影到相机的平面上(有效地将它们转换为屏幕上的 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() 调用,从而可以进行 2D 绘图! (这也将允许您进行命中测试,因为您可以轻松获取鼠标的当前像素坐标。)

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

    最难的部分是计算 hitboxes 在 2D 平面上的位置并处理叠加(如果两个项目在同一个地方,点击时选择哪个?)

    希望这有帮助:)

    【讨论】:

    • 这看起来是一种非常有用的技术,我可以在我的代码中的许多其他地方使用它,谢谢!我对 OpenGL 很陌生,所以我仍在学习像这样的绳索、提示和技巧,似乎很难获得。谢谢!
    【解决方案3】:

    我为 3d 编辑包编写了一个带有手柄的操纵器,但遇到了很多同样的问题。

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

    无论如何,我这样做的方法是在场景中添加一个操纵器对象,在绘制时,它会绘制所有手柄。它对边界框计算和选择做同样的事情。

    Reed 关于保持它们大小相同的想法对于存在于对象上的句柄很有趣,并且可能在那里起作用。对于一个操纵器,我发现它更像是一个 3d UI 元素,如果它不改变大小,它会更有用。我有一个错误,其中大小仅根据活动视口确定,这导致其他视口中出现可怕的巨大/微小操纵器,非常无用。如果您要将它们添加到场景中,您可能希望按视口添加它们,或者使它们实际上具有固定大小。

    【讨论】:

    • 你能解释一下你的“操纵器”是做什么的吗?它似乎与我在问题中描述的“句柄”不同?
    • 当然.. 操纵器是提供用于转换几何图形的句柄的小东西。这通常是对象、顶点、边、面或其他组件。这是 Maya 操纵器的图像:imanishi.com/mayablog/mayaPolygon/pC1.jpg
    【解决方案4】:

    我知道这个问题真的很老了。但以防万一有人需要:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-04-23
      • 1970-01-01
      • 2016-01-11
      • 2019-05-28
      • 2022-11-11
      • 1970-01-01
      • 2022-12-09
      相关资源
      最近更新 更多