5

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;

    }
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
Ramprasad
  • 7,981
  • 20
  • 74
  • 135
  • developer.android.com – Aks4125 Jan 01 '18 at 10:05
  • You may have better luck by looking at how game developers handle the case: https://gamedev.stackexchange.com/q/58480/6883 and https://gamedev.stackexchange.com/questions/18436/most-efficient-aabb-vs-ray-collision-algorithms as well other game development resources. – Morrison Chang Jan 05 '18 at 02:26

1 Answers1

5

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)


Find the intersection point of a ray with a primitive

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:

  1. Find the intersection point of the ray and the plane which is defined by the 3 points of the triangle primitive.
  2. Calculate the distance between the interection point and the start point of the ray.
  3. Test if the intersection point is in the direction of the ray (not in the opposite direction)
  4. Test if the intersection point is in or on the triangle contur.

Find the intersection point and the intersection distance:

enter image description here

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?

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • What is the primitive here? I have complex polygon 3D object...How do I bound my object? For example,In unity we can use Mesh Collider,how to do like this in openGLCode? Why this much of complexity for a basic thing. – Ramprasad Feb 28 '18 at 12:12
  • @Ramprasad Well, probably "Mesh Collider" does something similar. Unity is game engine and the goal of a game engine is to simplify things like that. OpenGL is low level. By the way this is not complicated, it's simple vector arithmetics and not especially for OpenGL – Rabbid76 Feb 28 '18 at 12:16
  • Yes.I accept it.Shall i need to add bounding boxes in OpenGl? Which one i need to compare with my ray intersection? ray intersects with all triangles in my object? – Ramprasad Feb 28 '18 at 12:25
  • Yes, from my experience that would gain a performance improvement. – Rabbid76 Feb 28 '18 at 12:27
  • How do I convert viewmatrix into triangles? – Ramprasad Feb 28 '18 at 12:40