Three.js RayCaster不会检测后期使用克隆几何体创建的网格

Three.js RayCaster不会检测后期使用克隆几何体创建的网格,three.js,Three.js,在下面的最小示例中(不要忘记修改three.min.js的URL),然后在窗口中打开html文件。你应该看到一个(不规则的)四面体。在画布上移动鼠标时,您应该看到从摄影机到鼠标的光线与场景对象的所有对象的相交数,在代码中使用以下行进行测试: raycaster.intersectObjects(scene.children,false); 因为除了光,只有四面体,它主要表示0或2,因为它计算了被无限光线相交的面数,并且因为我选择了双面材质: var material = new THREE.M

在下面的最小示例中(不要忘记修改three.min.js的URL),然后在窗口中打开html文件。你应该看到一个(不规则的)四面体。在画布上移动鼠标时,您应该看到从摄影机到鼠标的光线与场景对象的所有对象的相交数,在代码中使用以下行进行测试:

raycaster.intersectObjects(scene.children,false);
因为除了光,只有四面体,它主要表示0或2,因为它计算了被无限光线相交的面数,并且因为我选择了双面材质:

var material = new THREE.MeshLambertMaterial( { color: 0xd8f8b0, side: THREE.DoubleSide } );
现在单击复选框。另一个四面体是动态创建的,其几何体是第一个网格几何体的克隆体

geom2=geom.clone()

我通过向新几何体顶点的所有坐标添加1来偏移该几何体。但是,对于与新对象相交的大多数光线,光线投射器回答0。是否有错误,或者我是否忘记或误解了什么

如果几何体不是克隆(将clone=true;更改为clone=false;位于min.js顶部),则它可以工作

Three.js版本:r86

最小示例

html文件:

<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">
<script src="three.min.js"></script>
</head>

<body>
<div style="text-align: center;">
<canvas id="ze-canvas" width="800" height="600"></canvas>
<p>
<input type="checkbox" id="filBox"> click me
<p>
<span id="info-text"></span>
<p>
<script src="min.js"></script>
<script>visualiseur("ze-canvas","info-text","filBox");</script>
</div>
</body>
</html>

这是一个棘手的问题,但我找到了解决办法

简言之:添加

geom2.computeBoundingSphere();
仅在更改顶点之后

长版本:下面是我如何找到解决方案的。 我开始查看Geometry.js的源代码,查看Geometry中可能忽略的每个成员函数或变量。 我终于注意到了这个边界框和边界球体的东西,这是我以前在THREE.js中从未听说过的。回顾THREE.js文档的Geometry部分,提到了它们,但没有解释它们的用途

人们自然会认为,它们用于加速图形卡上的渲染,首先计算光线与长方体/球体的交点(我想这很快),如果没有交点,我们可以跳过整个对象

这是一个错误的假设:在我的最小示例中,第二个四面体确实出现了,尽管它的边界球是错误的

然后它变得更加奇怪。我让脚本在单击框时记录几何体的边界框和球体,一次是在克隆之前,一次是在下一次渲染过程之后。 他们永远不会得到一个边界框。 第一个几何体前后都有边界球体。 仅当clone=true时,第二个对象在渲染之前具有边界球体(因此创建时没有边界球体)。 渲染后,两个对象都有一个边界球体

结论:边界球体由光线投射器使用,而不是由渲染器使用。(这对我来说是个惊喜)

通过检查边界球体中心,我意识到第二个几何体的边界球体在克隆和移动顶点时是错误的,并且没有通过render()更新。 创建对象并调用render()时,将创建其边界球体,并且该球体是正确的。但是,如果更改顶点,并且即使将verticesNeedUpdate标志设置为true,边界球体也不会更新,则必须手动调用computeBoundingSphere()

更令人费解的是,当您调用render()而不是边界框时,会秘密创建边界球体

让我总结一下我对这一切的理解:

  • 边界球体由光线投射器使用,而不是渲染器使用

  • 如果其中一个使用边界框,我将忽略它(我没有花时间测试它)

  • 如果边界球体不存在,将在调用render()时创建它。如果它存在,则不会通过调用render()进行更新,即使将标志verticesNeedUpdate设置为true。

  • 边界框不是由render()创建的。

这是设计的行为还是一个bug

geom2.computeBoundingSphere();