嗨,我开始使用 Three.js 使用 webGL,我需要检测对球体的点击是否在其表面的某个部分内。
目前我可以检测球体是否被点击并获得点击点的坐标。现在我需要根据来自该球体的一组 3D 点来检测该点击是否在该球体的某个区域(另一个建议是可以的)。
球体在中心点,并且该点被保证在球体的表面上。现在我需要计算它是否只是在一个部分内。有什么建议么?我的问题似乎更数学化。我也更喜欢一种通用的方法来做到这一点,因为这些部分可能只是一个三角形或者可能是更复杂的图形。
嗨,我开始使用 Three.js 使用 webGL,我需要检测对球体的点击是否在其表面的某个部分内。
目前我可以检测球体是否被点击并获得点击点的坐标。现在我需要根据来自该球体的一组 3D 点来检测该点击是否在该球体的某个区域(另一个建议是可以的)。
球体在中心点,并且该点被保证在球体的表面上。现在我需要计算它是否只是在一个部分内。有什么建议么?我的问题似乎更数学化。我也更喜欢一种通用的方法来做到这一点,因为这些部分可能只是一个三角形或者可能是更复杂的图形。
我的第一个想法是将您的 3D 点投影到屏幕坐标上(即从世界坐标到视图坐标,就像在屏幕上绘制形状一样)。这为您提供了与感兴趣的表面相对应的视觉区域。这将是使用您的视图进行的简单 3D 到 2D 投影,然后您可以查看单击位置是否位于 2D 多边形中。
然后我意识到这种方法存在一个问题,即如果您的感兴趣区域绕过球体的背面,它将无法工作。
如果这是一个问题,您将需要沿相机方向构建鼠标单击的投影。如果您使用的是等距相机,这应该是可能的......
从该点画一条(大圆)射线。找到与曲线段最近的交点。当且仅当线段从右到左穿过射线时,该点才在曲线内。
一种解决方案是渲染伪彩色图像,其中每个区域都有自己的纹理颜色。然后对图像进行采样,使用 pesudocolor 作为数组索引。* 出于特殊原因,编码应该将值分散一点。
我已经结束了使用与建议不同的方法。
我正在使用矩阵行列式,其中:(T1,T2,T3)是形成三角形的点,X是我想知道它是否在这个三角形内的点,然后我简单地计算3个行列式,其中:
d1 = det([T1 T2 X])
d2 = det([T1 X T3])
d3 = det([T1 T2 X])
如果所有行列式的符号相同,则该点位于三角形内部。现在我根据选择区域形成一个三角形列表,并检查该点是否在这些三角形之一内。
this.Detector.triangleDetector = function(position, triangleArray){
for(var idxString in triangleArray){
var index = parseInt(idxString);
if(this.pointInTriangle(position, triangleArray[index].coords1, triangleArray[index].coords2, triangleArray[index].coords3))
return true;
}
return false;
}
该函数pointInTriangle(x,t1,t2,t3)
进行行列式验证。
this.Detector.pointInTriangle = function(x,T1,T2,T3){
var array1 = [coord1.x ,coord1.y ,coord1.z];
var array2 = [coord2.x ,coord2.y ,coord2.z];
var array3 = [coord3.x ,coord3.y ,coord3.z];
var zero = 0;
var A = [[zero,zero,zero],[zero,zero,zero],[zero,zero,zero]];
var d1,d2,d3;
A[0][0] = position.x;
A[0][1] = position.y;
A[0][2] = position.z;
A[1][0] = array2[0];
A[1][1] = array2[1];
A[1][2] = array2[2];
A[2][0] = array3[0];
A[2][1] = array3[1];
A[2][2] = array3[2];
d1 = MyMath.determinant(A,3);
A[0][0] = array1[0];
A[0][1] = array1[1];
A[0][2] = array1[2];
A[1][0] = position.x;
A[1][1] = position.y;
A[1][2] = position.z;
d2 = MyMath.determinant(A,3);
A[1][0] = array2[0];
A[1][1] = array2[1];
A[1][2] = array2[2];
A[2][0] = position.x;
A[2][1] = position.y;
A[2][2] = position.z;
d3 = MyMath.determinant(A,3);
if((d1>=0 && d2 >=0 && d3>=0) || (d1<=0 && d2 <=0 && d3<=0)){
return true;
}
return false;
};