如何实现平移,缩放,旋转小控件来操纵3D对象的变换?


11

我正在开发基本的3D编辑器。它使用OpenGL渲染3D世界。现在,我的场景只是几个大小不同的盒子,而我正处于一个阶段,我希望能够选择每个盒子,然后对其进行移动/缩放/旋转以实现所需的任何变换。

我该如何解决以下问题:既实现这些工具的Gizmos(或手柄,又或者人们通常如何称呼它们)的渲染,又要在每个轴上拾取它们以用鼠标执行变换中的更改?为了清楚起见: 在此处输入图片说明

到目前为止,我的研究表明,最干净的方法是在Gizmo中为每个箭头设置一个与轴对齐的边界框,然后在每个正方形中使另一个箭头对齐(将对象沿平面而不是单轴移动),然后从鼠标投射光线定位并查看其碰撞。但这对我来说仍然太抽象了,我希望进一步了解该算法的运行方式(伪代码已足够)


1
通常,您将使用鼠标位置向世界发出光线,看看您是否碰到了Gizmo。您也可以将Gizmo转换为屏幕空间,以便在那里进行碰撞检测。通常,尽管您只是执行从射线到线段类型的事物的距离。旋转通常作为虚拟轨迹球进行。请参阅游戏编程宝石1中的Melax。翻译几乎是一个点积,规模也是一个点积。
RandyGaul

Answers:


9

在e-on上的某个时候,我保持了Vue产品线的传统。
我可以告诉你,这将需要几天的时间,全职。
除非找到某种库或超级巧妙的方法,否则经典方法是单击时在窗口中获取鼠标的坐标,如果它是相对于视口的相对坐标,则只需将x和y除以宽度和高度即可,获得[0,1]范围内的向量(浮点2d)。减去(0.5,0.5)即可使x和y都进入[-0.5,0.5]范围。
然后,通过简单地将x和y用作射线x和y,从该坐标发出射线,并将z设置为焦距。有时,长宽比会给操作带来麻烦。有点摆弄和试错会帮助您解决问题。
然后,您需要检查与Gizmos元素的交集,既可以是生成的网格,也可以是在Blender或其他DCC中建模的网格,或者是可以相互连接的网格零件...只需将这些网格零件用作ray /三角形相交查询。
或者,如果有,请根据您的Gizmo外观和零件使用ray / cylinder,ray / sphere。
您需要具有相交例程,该例程能够在碰撞的图元上应用转换矩阵。极其重要,因为您的Gizmo会随它所移动的对象一起平移,旋转并以与相机的距离的倒数进行缩放,以便在屏幕上保持固定的投影大小。
然后,您具有交互作用部分,最简单的方法是获取鼠标第一次“向下移动”事件时的点的变化量,以及当前“鼠标移动”位置(以纯2D形式),并将该变化量用作当前轴的移动在世界空间中,乘以k您凭经验确定的部分。根据您的内部单位,像素与当前缩放比例等。
最后一步只是将Gizmo的矩阵应用于被操纵的对象,以便它跟随它。

我告诉你,这是一个艰苦的实施过程,如果您在空闲时间这样做,则需要超过一周的时间。如果您要完全发现该领域,则需要几个星期。如果您的周末忙于其他活动,则超过一个月:)

我建议您从英特尔下载Embree 2.0来为您执行射线/三角形相交查询,因此您不必担心对其进行编码。或者您可以轻而易举地从Blender复制/粘贴并改编代码...我认为它们已迁移到Apache许可证?在法律上应该是可能的。


1
非常感谢您的回答。确实有帮助。我知道当我被一个看似简单的任务淹没时,我并不疯。我低估了它的难度,并最终在同一问题上被困了好几天。.下次我去处理这个问题时,我一定会制定一个好的计划。谢谢
Grimshaw 2014年

0

对于机械手-翻译器,我使用以下算法:

1)当鼠标向下移动时,我们需要检查射线是否与箭头相交。例如,我们考虑X箭头。我们在世界空间中构造Ray(基于相机视锥和鼠标位置)。我们构建一个x轴所在的平面:其法线等于V交叉X交叉V,其中V-从中心到摄像机的矢量,X-表示x轴。然后我们将射线与平面相交,因此我们在世界坐标中找到相交点。然后,我们将x轴线段和所得点投影到屏幕上,找到投影线段和屏幕上的投影点之间的距离。如果少于几个像素,则鼠标将与轴相交。我们还计算选择中心和交点之间的世界空间增量矢量。

我们对3个轴执行此过程,因此我们找到了到所有轴的距离。找到最小距离。因此我们发现了鼠标与哪条轴相交。

2)鼠标移动时。我们知道对象从哪个轴移动(从1开始)。我们找到了射线与平面的世界空间相交(如1)。此外,我们将交点投影在对象移动的线上。最终操纵器位置=交点+增量。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.