我正在构建一个简单的实体建模应用程序。用户需要能够在正交视图和透视视图中操纵对象。例如,当屏幕上有一个框并且用户点击它以选择它时,它需要在角落和中心处获得“手柄”,以便用户可以将鼠标移动到这样的手柄上并将其拖动到放大或移动盒子。
有什么策略可以做到这一点,哪一个是最好的策略?我可以想到两个显而易见的问题:
1)将手柄视为3d对象。即对于一个盒子,在“主”框的角落添加小盒子到场景。问题:这在透视图中不起作用,我需要确定相对于当前缩放级别的框的大小(无论用户放大/缩小多远,手柄都需要具有相同的大小)< / p>
2)渲染场景后添加手柄。渲染到屏幕外缓冲区,以某种方式确定角落的2d位置,并使用常规的2D绘图技术绘制手柄。问题:我将如何进行测试?我还需要做一个两阶段的测试方法;如何在3D渲染图像上绘制2d?回到GDI?
这两种方法可能存在更多问题。有解决这个问题的行业标准方法吗?
我正在使用OpenGL,如果这有所不同。
答案 0 :(得分:2)
我会将把手视为3D对象。这提供了许多优点 - 它更加一致,它们表现良好,命中测试很容易等等。
如果您希望手柄的大小恒定,您仍然可以将它们视为3D对象,但您必须根据与相机的距离来适当缩放它们的大小。这有点麻烦,但由于通常只有少量手柄,而且这些手柄通常都是小物件,因此性能应该很好。
然而,我实际上是说让手柄随场景缩放。只要你选择一个让它们脱颖而出的手柄的渲染风格(即:亮橙色框等),透视效果(背景中较小的手柄)实际上使得最终用户在很多方面更容易使用它们。很难从3D场景中获得深度感 - 对手柄的透视效果有助于提供更多视觉线索,了解手柄在屏幕上的“深度”。
答案 1 :(得分:1)
首先,将把手/角落坐标投影到相机的平面上(有效地将它们转换为屏幕上的2D坐标;根据屏幕尺寸对其进行标准化。)
这是一些启用正交/ 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恢复旧的模型视图/投影矩阵:)
最困难的部分是计算命中箱落在2D平面上并处理重叠(如果两个项目到同一个地方,在点击时选择哪个?)
希望这有助于:)
答案 2 :(得分:1)
我编写了一个带有3D编辑包手柄的操纵器,并遇到了很多这些相同的问题。
首先,有一个开源操纵器。我在最近的搜索中找不到它,可能是因为这些东西有很多名字 - 三维小工具,小玩意儿,操纵器,平衡环等等。
无论如何,我这样做的方法是在场景中添加一个操纵器对象,绘制时绘制所有的手柄。它对边界框计算和选择做了同样的事情。
Reed关于保持它们大小相同的想法对于存在于对象上的句柄很有意义,并且可能在那里工作。对于操纵器,我发现它更像是一个3d UI元素,如果不改变大小,它就更有用了。我有一个错误,其大小只是根据活动视口确定,导致其他视口中的可怕的巨大/微小操纵器,非常无用。如果您要将它们添加到场景中,您可能希望为每个视口添加它们,或者使它们实际上具有固定大小。
答案 3 :(得分:1)
我知道这个问题真的很老了。但万一有人需要它:
文章很好,底部有一个有趣的链接部分。