javascript - 将鼠标坐标转换为 3D 平面图

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

我正在使用 javascript/jquery(基于 DOM,而非 Canvas )构建某种拖放应用程序。

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

它在 2D 平面上工作,问题是当我在 3D 中旋转场景时,对象位置不反射(reflect)实际鼠标位置,而是在 3D 中转换的坐标

示例: exemple

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 平面图的鼠标坐标,但此时无法找到真正的解决方案。

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

有什么想法吗?

谢谢

最佳答案

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

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

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

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

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

然后,您可以组合将此特定 3D 点映射到屏幕的操作;这通常用 3D 变换矩阵 ModelMatrixViewMatrixProjectionMatrix 以及由 2D 屏幕原点 确定的视口(viewport)变换来描述origin_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 平面图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12503219/

相关文章:

javascript - jquery 返回 false 不在从 onclientclick 按钮事件调用的函数中工作

javascript - Three.js - 创建带有纹理的平面圆..?

math - 如何使用three.js绘制自定义3d表面?

javascript - 尝试从 Blob 创建文件,但输出文件的大小无效

javascript - 我可以在手机屏幕中间放置工具提示吗?

javascript - 带有滚动条的 Jquery Fancybox 可拖动问题

java - 如何确定 vector 3D 形状的绘制顺序

javascript - 将多选元素的选择存储在字符串中

javascript - 如何在javascript中比较负数

javascript - 使用 Ajax 加载页面并将数据发送到页面