I am working in 3D object rendering using OpenGLES 2.0 with Android,Java code.How to identify click inside the 3D object or outside 3D object using following code near and far positions?
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?
You have to verify if you hit any of the primitives of the object.
The point at the near plane and the point at the far plane define a ray through the world:
float[] nearPos = unProject(viewMatrix, projMatrix, screenX, screenY, 0);
float[] farPos = unProject(viewMatrix, projMatrix, screenX, screenY, 1);
pseudo code:
R0 = nearPos
D = normalize(farPos - nearPos)
To find the surface which is hit by the ray, the distance of the intersection point of each surface (primitive) with the ray and the start point of the ray has to be calculated. The surface which has the lowest distance (in the ray direction), is hit.
To find the distance of the intersection point of a ray with a triangle primitive, the following steps has to be done:
Find the intersection point and the intersection distance:
A plane is defined by a norm vector (NV
) and a point on the plane (P0
). If a triangle is given by the 3 points PA
, PB
and PC
, the plane can be calculated as follows:
P0 = PA
NV = normalize( cross( PB-PA, PC-PA ) )
The intersection of a ray with a plane is calculated by substituting the equation of the ray
P_isect = dist * D + R0
into the equation of the plane dot( P_isect - P0, NV ) == 0
.
It follows:
dist_isect = dot( P0 - R0, NV ) / dot( D, NV )
P_isect = R0 + D * dist_isect
Test if the intersection point is in the direction of the ray:
The intersection point is in the direction of the ray, if `dist_isect is greater or equal 0.0.
Test if the intersection point is in or on the triangle contur
To find out, if a point is inside a triangle, has to be tested, if the line from a corner point to the intersection point is between the to legs which are connect to the corner point:
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 )
}
See also: Is it possble get which surface of cube will be click in OpenGL?