了解如何使用@mediapipe/hands 和 Three.js 创建具有深度的完整 3D 手控制器。
今天将展示如何仅使用双手、网络摄像头和网络浏览器来控制 3D 场景中的元素。这里的关键重点是将 2D 屏幕转换为 3D 空间,并实现完全深度控制。
为了实现这个结果,我们将使用Mediapipe和Three.js。
介绍之前可以先体验一下使用这个技术的游戏:
https://caiobassetti.com/experiments/spaceship-control/
安装:
需要创建@mediapipe/hands实例来检测手部特征点。
建了一个包含此实现的class调用MediaPipeHands,因此我们可以轻松地将其添加到代码中并在任何地方重复使用它。
onMediaPipeHandsResults是库的一个回调,它返回了提到的坐标,它来自hands.onResults。
让我们用 Three.js 创建我们的 WebGL 场景,只包含一些我们可以交互的元素。
导入它并初始化它即可拥有一个场景:
创建控件
让我们开始使用坐标,它是@mediapipe/hands我之前提到的笛卡尔坐标。
这是参考资料,这样您就知道我在说什么,并了解我们将使用的值。
为了在 x/y 轴上移动元素,我将仅选择一个点,即9。MIDDLE_FINGER_MCP,我的选择仅基于此坐标的位置,它位于一切的中心并且有意义。
我们在这次探索中只使用一只手,因此坐标的前 21 个索引很重要。
如果您想使用两只手,请使用相同的数组并从索引 21 开始读取值。
if (landmarks.multiHandLandmarks.length === 1) {
for (let l = 0; l < 21; l++) {
this.handsObj.children[l].position.x = -landmarks.multiHandLandmarks[0][l].x + 0.5;
this.handsObj.children[l].position.y = -landmarks.multiHandLandmarks[0][l].y + 0.5;
this.handsObj.children[l].position.z = -landmarks.multiHandLandmarks[0][l].z;
}
}
效果如下:
正如你所注意到的,坐标点即使在 3D 空间中也具有相同的比例,这是因为 @mediapipe/hands 没有合适的 z 轴,它是 2D。
手势
碰撞测试
让我们计算光标和物体之间的碰撞并开始抓住它们。
写了一个简单的 AABB 测试,因为在我的测试中,它比使用射线投射器更准确、性能更好。但请记住,每种情况都是一个案例,所以也许使用另一种算法甚至使用 Rasycater 会更好!
效果如下: