如何使用近距离和远距离识别 3D 对象内部或外部 3D 对象的点击
How to identify click inside the 3D object or outside 3D object using near and far positions
我正在使用带有 Android、Java code.How 的 OpenGLES 2.0 进行 3D 对象渲染,使用以下代码近距离和远距离识别 3D 对象内部或外部 3D 对象的点击?
public static PointF screenToWorld(float[] viewMatrix,
float[] projMatrix, float screenX, float screenY) {
float[] nearPos = unProject(viewMatrix, projMatrix, screenX, screenY, 0);
float[] farPos = unProject(viewMatrix, projMatrix, screenX, screenY, 1);
Log.d(LOGTAG,"nearPos ->"+nearPos.length+" "+nearPos);
Log.d(LOGTAG,"farPos ->"+farPos.length+" "+farPos);
// The click occurred in somewhere on the line between the two points
// nearPos and farPos. We want to find
// where that line intersects the plane at z=0
float distance = nearPos[2] / (nearPos[2] - farPos[2]); // Distance between nearPos and z=0
float x = nearPos[0] + (farPos[0] - nearPos[0]) * distance;
float y = nearPos[1] + (farPos[1] - nearPos[0]) * distance;
return new PointF(x, y);
}
private static float[] unProject(float[] viewMatrix,
float[] projMatrix, float screenX, float screenY, float depth) {
float[] position = {0, 0, 0, 0};
int[] viewPort = {0, 0, 1, 1};
GLU.gluUnProject(screenX, screenY, depth, viewMatrix, 0, projMatrix, 0,
viewPort, 0, position, 0);
position[0] /= position[3];
position[1] /= position[3];
position[2] /= position[3];
position[3] = 1;
return position;
}
How to identify click inside the 3D object or outside 3D objec?
您必须验证是否击中了对象的任何基元。
近平面的点和远平面的点定义了一条穿过世界的射线:
float[] nearPos = unProject(viewMatrix, projMatrix, screenX, screenY, 0);
float[] farPos = unProject(viewMatrix, projMatrix, screenX, screenY, 1);
伪代码:
R0 = nearPos
D = normalize(farPos - nearPos)
找到射线与图元的交点
要找到被射线击中的表面,必须计算每个表面(基元)与射线的交点与射线起点的距离。距离最短的表面(在光线方向)被击中。
要找到一条射线与一个三角形图元的交点的距离,必须完成以下步骤:
- 找到射线与由三角形基元的 3 个点定义的平面的交点。
- 计算交点与射线起点的距离
- 测试交点是否在光线方向(不是反方向)
- 判断交点是在三角形内还是在三角形上
求交点和交点距离:
平面由范数向量 (NV
) 和平面上的一个点 (P0
) 定义。如果用PA
、PB
、PC
3个点给出一个三角形,平面可以这样计算:
P0 = PA
NV = normalize( cross( PB-PA, PC-PA ) )
射线与平面的交点代入射线的方程
P_isect = dist * D + R0
转化为平面方程dot( P_isect - P0, NV ) == 0
.
如下:
dist_isect = dot( P0 - R0, NV ) / dot( D, NV )
P_isect = R0 + D * dist_isect
测试交点是否在光线方向:
如果`dist_isect大于等于0.0,则交点在光线方向。
测试交点是在三角形内部还是在三角形内部
要找出一个点是否在三角形内部,必须测试从角点到交点的线是否在连接到角点的到腿之间:
bool PointInOrOn( P1, P2, A, B )
{
CP1 = cross( B - A, P1 - A )
CP2 = cross( B - A, P2 - A )
return dot( CP1, CP2 ) >= 0
}
bool PointInOrOnTriangle( P, A, B, C )
{
return PointInOrOn( P, A, B, C ) &&
PointInOrOn( P, B, C, A ) &&
PointInOrOn( P, C, A, B )
}
另见:Is it possble get which surface of cube will be click in OpenGL?
我正在使用带有 Android、Java code.How 的 OpenGLES 2.0 进行 3D 对象渲染,使用以下代码近距离和远距离识别 3D 对象内部或外部 3D 对象的点击?
public static PointF screenToWorld(float[] viewMatrix,
float[] projMatrix, float screenX, float screenY) {
float[] nearPos = unProject(viewMatrix, projMatrix, screenX, screenY, 0);
float[] farPos = unProject(viewMatrix, projMatrix, screenX, screenY, 1);
Log.d(LOGTAG,"nearPos ->"+nearPos.length+" "+nearPos);
Log.d(LOGTAG,"farPos ->"+farPos.length+" "+farPos);
// The click occurred in somewhere on the line between the two points
// nearPos and farPos. We want to find
// where that line intersects the plane at z=0
float distance = nearPos[2] / (nearPos[2] - farPos[2]); // Distance between nearPos and z=0
float x = nearPos[0] + (farPos[0] - nearPos[0]) * distance;
float y = nearPos[1] + (farPos[1] - nearPos[0]) * distance;
return new PointF(x, y);
}
private static float[] unProject(float[] viewMatrix,
float[] projMatrix, float screenX, float screenY, float depth) {
float[] position = {0, 0, 0, 0};
int[] viewPort = {0, 0, 1, 1};
GLU.gluUnProject(screenX, screenY, depth, viewMatrix, 0, projMatrix, 0,
viewPort, 0, position, 0);
position[0] /= position[3];
position[1] /= position[3];
position[2] /= position[3];
position[3] = 1;
return position;
}
How to identify click inside the 3D object or outside 3D objec?
您必须验证是否击中了对象的任何基元。
近平面的点和远平面的点定义了一条穿过世界的射线:
float[] nearPos = unProject(viewMatrix, projMatrix, screenX, screenY, 0);
float[] farPos = unProject(viewMatrix, projMatrix, screenX, screenY, 1);
伪代码:
R0 = nearPos
D = normalize(farPos - nearPos)
找到射线与图元的交点
要找到被射线击中的表面,必须计算每个表面(基元)与射线的交点与射线起点的距离。距离最短的表面(在光线方向)被击中。
要找到一条射线与一个三角形图元的交点的距离,必须完成以下步骤:
- 找到射线与由三角形基元的 3 个点定义的平面的交点。
- 计算交点与射线起点的距离
- 测试交点是否在光线方向(不是反方向)
- 判断交点是在三角形内还是在三角形上
求交点和交点距离:
平面由范数向量 (NV
) 和平面上的一个点 (P0
) 定义。如果用PA
、PB
、PC
3个点给出一个三角形,平面可以这样计算:
P0 = PA
NV = normalize( cross( PB-PA, PC-PA ) )
射线与平面的交点代入射线的方程
P_isect = dist * D + R0
转化为平面方程dot( P_isect - P0, NV ) == 0
.
如下:
dist_isect = dot( P0 - R0, NV ) / dot( D, NV )
P_isect = R0 + D * dist_isect
测试交点是否在光线方向:
如果`dist_isect大于等于0.0,则交点在光线方向。
测试交点是在三角形内部还是在三角形内部
要找出一个点是否在三角形内部,必须测试从角点到交点的线是否在连接到角点的到腿之间:
bool PointInOrOn( P1, P2, A, B )
{
CP1 = cross( B - A, P1 - A )
CP2 = cross( B - A, P2 - A )
return dot( CP1, CP2 ) >= 0
}
bool PointInOrOnTriangle( P, A, B, C )
{
return PointInOrOn( P, A, B, C ) &&
PointInOrOn( P, B, C, A ) &&
PointInOrOn( P, C, A, B )
}
另见:Is it possble get which surface of cube will be click in OpenGL?