将鼠标坐标转换为3D计划

Jul*_*ian 6 javascript 3d jquery drag-and-drop mouse-coordinates

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

我们的想法是能够在3D场景上拖动div(以3D旋转的div).

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

插图例子: 为例

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 ); 
}
Run Code Online (Sandbox Code Playgroud)

早期的解决方案是基于初始位置计算鼠标位置和对象之间的差异,并在拖动期间将其添加到对象位置.它工作正常,但动画真是波涛汹涌而且根本不光滑.

我确信有一种更简单的方法来获得相对于3D计划的鼠标坐标,但此时无法找到真正的解决方案.

关于此主题的大多数搜索结果都指向面向游戏的语言或canvas/webgl问题.

有任何想法吗 ?

谢谢

com*_*orm 2

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

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

  • 3D 原点O
  • 两个 3D 向量UV,表示 U 轴和 V 轴的方向

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

point3d P = O + u*U + v*V
Run Code Online (Sandbox Code Playgroud)

然后,您可以组合将这个特定 3D 点映射到屏幕的操作;这通常用 3D 变换矩阵ModelMatrixViewMatrix、 和ProjectionMatrix以及由 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
Run Code Online (Sandbox Code Playgroud)

注意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
Run Code Online (Sandbox Code Playgroud)

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