0

嗨,我开始使用 Three.js 使用 webGL,我需要检测对球体的点击是否在其表面的某个部分内。

目前我可以检测球体是否被点击并获得点击点的坐标。现在我需要根据来自该球体的一组 3D 点来检测该点击是否在该球体的某个区域(另一个建议是可以的)。

球体在中心点,并且该点被保证在球体的表面上。现在我需要计算它是否只是在一个部分内。有什么建议么?我的问题似乎更数学化。我也更喜欢一种通用的方法来做到这一点,因为这些部分可能只是一个三角形或者可能是更复杂的图形。

4

4 回答 4

0

我的第一个想法是将您的 3D 点投影到屏幕坐标上(即从世界坐标到视图坐标,就像在屏幕上绘制形状一样)。这为您提供了与感兴趣的表面相对应的视觉区域。这将是使用您的视图进行的简单 3D 到 2D 投影,然后您可以查看单击位置是否位于 2D 多边形中。

然后我意识到这种方法存在一个问题,即如果您的感兴趣区域绕过球体的背面,它将无法工作。

如果这是一个问题,您将需要沿相机方向构建鼠标单击的投影。如果您使用的是等距相机,这应该是可能的......

于 2012-12-17T16:29:32.787 回答
0

从该点画一条(大圆)射线。找到与曲线段最近的交点。当且仅当线段从右到左穿过射线时,该点才在曲线内。

于 2012-12-17T17:48:11.960 回答
0

一种解决方案是渲染伪彩色图像,其中每个区域都有自己的纹理颜色。然后对图像进行采样,使用 pesudocolor 作为数组索引。* 出于特殊原因,编码应该将值分散一点。

于 2012-12-17T21:22:05.423 回答
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;
};
于 2012-12-18T13:07:00.573 回答