您好我正在使用Three.js开始使用webGL,我需要检测一个球体上的点击是否在其表面的某个部分内。
目前,我可以检测球体是否被点击并获得点击的点的坐标。现在我需要的是根据该球体的一个3D点数来检测该点击是否在该球体的某个区域内(另一个建议是可以的)。
球体位于中心点,并且该点被限制在球体的表面上。现在我需要计算它是否只是在一节内。有什么建议?我的问题接缝更加数学化。 此外,我更喜欢通用的方法,因为这些部分可能只是一个三角形或可能是更复杂的数字。
答案 0 :(得分:0)
我的第一个想法是将3D点投影到屏幕坐标(即从世界坐标到视图坐标,就像在屏幕上绘制形状一样)。这为您提供了与感兴趣表面相对应的视觉区域。这将是一个使用您的视图进行简单的3D到2D投影,然后您可以看到点击位置是否位于2D多边形中。
然后我意识到这种方法存在问题,即如果您感兴趣的区域绕到球体的后表面,它将无法工作。
如果这是一个问题,则需要沿摄像机方向构建鼠标单击投影。如果您使用等距相机,这应该是可能的......
答案 1 :(得分:0)
从该点绘制(大圆)光线。找到与曲线段最近的交点。当且仅当片段从右到左穿过光线时,该点在曲线内。
答案 2 :(得分:0)
一种解决方案是渲染伪彩色图像,其中您的区域每个都具有纹理的颜色。然后对图像进行采样,使用pesudocolor作为数组索引。 *出于特殊原因,编码应该将值扩散一点。
答案 3 :(得分:0)
我结束时使用了与建议不同的方法。
我正在使用矩阵行列式,其中:(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;
};