Three.js中的射线(Ray)如何忽略透明像素。

7

我有一些包含平面几何的Vector3ds,它们使用透明png作为它们的材质。

我的问题是Raycaster会选中整个对象,所以在材质附近点击就足以激活相应的功能。

有没有可能从射线跟踪器中隐藏网格的透明部分?

在Alex的帮助下,我已经得到了物体上的实际点。

现在如何将其转换为图像上的像素,以测试透明度?


2
你能测试交点处的像素值吗? - Mapsy
嗯,也许吧。我的射线投射器变量intersects = ray.intersectObjects(targetList, true);正在测试大量对象,我该如何检查它实际找到的像素呢? - beek
1
你需要将反射点与图像在空间中的位置和尺寸进行关联,并将这个相对点转换为图像的相应像素。如果像素是透明的,则可以丢弃正结果。请记住,此测试将需要考虑图像的X、Y和Z旋转。 - Mapsy
我正在努力实现这个概念。有没有具体的代码想法,而不是高层次的视图? - beek
1个回答

6

我不熟悉 Three.js,但是在线文档向我表明,Raycast算法是基于空间中物体的分布而不是它们的组成进行计算的。在这方面,我认为没有特定的方法可以“通知” Raycast,我们仅希望测试不透明像素。

我考虑首先使用Three.js中的 Raycast.intersectObjects(pObjects, pRecursive) 来分析哪些对象与射线的空间范围广泛碰撞。一旦对象被过滤,您需要执行特定的测试来确定射线是否与不透明像素发生碰撞。

一个简单的方法是取我们保证与射线相撞的物体,并确定射线穿过该物体时的中心位置。(这将变得更加复杂,具体取决于对象是否可以缩放,或者对象/射线是否可以旋转。)可以使用三角函数找到射线在3D空间中的交点的绝对位置,这将需要考虑您的射线的nearfar值。

通过了解图像的位置和尺寸,您可以将射线投射的坐标在您的3D世界中转换为相对于您使用的图像的离散2D坐标。

例如,想象一个简单的2D案例。如果您有一个坐落在原点上的50px²图像,并且射线与图像在位置(25,25)相交,则可以使用此信息索引像素数据数组并测试像素的alpha值。由于PNG图像数据存储RGBA数据,因此您正在查看每个像素四个字节。因此,您需要一个实现类似于下面示例的内容,因为图像数据是连续存储的。

byte lPixelRed   = bitmap.getData()[(X  + Y*bitmap.getWidth())*4];
byte lPixelGreen = bitmap.getData()[(X  + Y*bitmap.getWidth())*4 + 1];
byte lPixelBlue  = bitmap.getData()[(X  + Y*bitmap.getWidth())*4 + 2];
byte lPixelAlpha = bitmap.getData()[(X  + Y*bitmap.getWidth())*4 + 3];

一旦找到像素数据的区域,您可以测试alpha字节以确定它们是不透明的(0xFF)还是透明的(0x00)。这可以用来确定raycast是否已成功与您的对象碰撞。


1
好的,非常有帮助。我会再试一次。谢谢! - beek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接