【问题标题】:Translate mouse coordinates to a 3D plan将鼠标坐标转换为 3D 平面图
【发布时间】:2012-09-12 06:20:25
【问题描述】:

我正在 javascript/jquery 中构建某种拖放应用程序(基于 DOM,而不是画布)。

这个想法是能够在 3D 场景中拖动 div(在 3D 中旋转的 div)。

它适用于 2D 平面图,问题是当我在 3D 中旋转场景时,对象位置并不反映实际的鼠标位置,而是在 3D 中转换的坐标

图解示例:

EXEMPLE ON JSFIDDLE

我希望对象相对于鼠标的绝对位置移动。

我这样计算鼠标位置:

document.addEventListener(gestureMove, function (event) {
  if (mouseDown == true) {
  event.preventDefault();
  moveX = (event.pageX - $('#scene').offset().left);
  moveY = (event.pageY - $('#scene').offset().top);
}

#scene { 
  width: 1000px;
  height: 1000px;
  -webkit-transform-style: preserve-3d;
  -webkit-transform: rotateX( 35deg ); 
}

早期的解决方案是根据初始位置计算鼠标位置与对象之间的差异,并在拖动过程中将其添加到对象位置。它可以工作,但动画真的很不稳定,一点也不流畅。

我确信有一种更简单的方法可以获取相对于 3D 计划的鼠标坐标,但目前无法找到真正的解决方案。

关于这个主题的大部分搜索结果都指向游戏语言或画布/webgl 问题。

有什么想法吗?

谢谢

【问题讨论】:

标签: javascript jquery 3d drag-and-drop mouse-coordinates


【解决方案1】:

假设您的鼠标位置是屏幕的绝对位置,并且您想直接根据鼠标位置在 3D 平面上抓取和滑动对象:

您可以将您的 3D 目标平面表示为:

  • 一个3D原点O
  • 两个 3D 向量 UV,分别代表 U 轴和 V 轴的方向

那么,对应平面坐标[u,v]的给定3D点为:

point3d P = O + u*U + v*V

然后,您可以组合将这个特定 3D 点映射到屏幕的操作;这通常用 3D 变换矩阵 ModelMatrixViewMatrixProjectionMatrix 以及由 2D 屏幕原点 origin_2d 和 2D 缩放矢量 scale_2d 确定的视口变换来描述。要以一种容易逆转的方式解决问题,请将所有内容都提升到齐次坐标,方法是为每个坐标添加.w-坐标。这个额外的坐标充当比例因子——要返回笛卡尔坐标,您需要将齐次的 .x.y 值除以 .w 值:

P_hom = [u, v, 1] * [U.x, U.y, U.z, 0] = [u, v, 1] * TexMatrix
                    [V.x, V.y, V.z, 0]
                    [O.x, O.y, O.z, 1]

P_clip_hom = P_hom * ModelMatrix * ViewMatrix * ProjectionMatrix
           = P_hom * ModelViewProjectionMatrix

screenpos_hom = P_clip_hom * [scale_2d.x     0        0] = P_clip_hom * PortMatrix
                             [   0        scale_2d.y  0]
                             [   0           0        0]
                             [origin_2d.x origin_2d.y 1]

So, screenpos_hom = [u, v, 1] * TexMatrix * ModelViewProjectionMatrix * PortMatrix
                  = [u, v, 1] * TexToScreenMatrix

-> [screenpos.x, screenpos.y] = [screenpos_hom.x, screenpos_hom.y] / screenpos_hom.w

注意TexToScreenMatrix 是一个 3x3 矩阵;你应该可以反转它:

UV_2d_hom = [screenpos.x, screenpos.y, 1] * (TexToScreenMatrix)^-1

-> [u, v] = [UV_2d_hom.x, UV_2d_hom.y] / UV_2d_hom.w

最后,您可以直接使用[u,v] 坐标,也可以使用它们重新创建3D 点P,如上所述。

【讨论】:

  • 谢谢!但我不确定如何在 javascript 中使用 3D 转换矩阵。另外,我的例子中的“w”是什么?
  • 恐怕我不知道这些是如何绑定在 javascript/webkit 平台上的。如果您不能直接获得 webkit 转换矩阵,您可能必须匹配 javascript 中的 3D 数学 - 例如,如果您使用 rotateX(35deg),很遗憾您需要为 35 设置自己的 3D X 旋转矩阵度并将其乘以您自己的ViewMatrix...
  • 至于“w”,我试图在我的回答中简要解释一下;除以“w”是让您首先进行 3D 透视的原因。如果您想比这更好地理解它,则需要对基本 3D 数学进行更长更好的演示;在3D projection 上尝试维基百科。
  • 如果您可以通过谷歌搜索“3D”、“透视”、“投影”和“同质”等关键字找到的维基百科文章和其他链接不好,那么最好的选择可能是使用一本真正的书。我可以推荐 Alan Watt 的 3D Computer Graphics,但是有很多不错的文本可供选择——看看你可以在当地大学图书馆找到什么。
  • 似乎有可能获得 webkit 转换矩阵...我会深入研究的。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-25
  • 2011-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多