Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
208 views
in Technique[技术] by (71.8m points)

android - Is it possible get which surface of cube will be click in OpenGL?

I already create a cube and its spin perfectly. And my task is which spinning cube you click. ex, if you click on red color of the surface in a cube then, I will win, but I can not able to find surface view of click of cube,

Edited

enter image description here
i want surface of where i touch.

Here is my code of renderer:

public void onDrawFrame(GL10 arg0) {
    //              GLES20.glEnable(GLES20.GL_TEXTURE_CUBE_MAP);
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
    GLES20.glUseProgram(iProgId);

    cubeBuffer.position(0);
    GLES20.glVertexAttribPointer(iPosition, 3, GLES20.GL_FLOAT, false, 0, cubeBuffer);
    GLES20.glEnableVertexAttribArray(iPosition);

    texBuffer.position(0);
    GLES20.glVertexAttribPointer(iTexCoords, 3, GLES20.GL_FLOAT, false, 0, texBuffer);
    GLES20.glEnableVertexAttribArray(iTexCoords);

    GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
    GLES20.glBindTexture(GLES20.GL_TEXTURE_CUBE_MAP, iTexId);
    GLES20.glUniform1i(iTexLoc, 0);

    // Draw a cube.
    // Translate the cube into the screen.
    Matrix.setIdentityM(m_fIdentity, 0);
    //               Matrix.translateM(m_fIdentity, 0, 0.0f, 0.8f, -3.5f);

    // Set a matrix that contains the current rotation.
    Matrix.setIdentityM(mCurrentRotation, 0);
    Matrix.rotateM(mCurrentRotation, 0, mDeltaX, 1.0f, 0.0f, 0.0f);
    Matrix.rotateM(mCurrentRotation, 0, mDeltaY, 0.0f, 1.0f, 0.0f);
    Matrix.rotateM(mCurrentRotation, 0, mDeltaZ, 0.0f, 0.0f, 1.0f);

    mDeltaX = 0.0f;
    mDeltaY = 0.0f;
    mDeltaZ = 0.0f;

    // Multiply the current rotation by the accumulated rotation, and then set the accumulated
    // rotation to the result.
    Matrix.multiplyMM(mTemporaryMatrix, 0, mCurrentRotation, 0, mAccumulatedRotation, 0);
    System.arraycopy(mTemporaryMatrix, 0, mAccumulatedRotation, 0, 16);

    // Rotate the cube taking the overall rotation into account.
    Matrix.multiplyMM(mTemporaryMatrix, 0, m_fIdentity, 0, mAccumulatedRotation, 0);
    System.arraycopy(mTemporaryMatrix, 0, m_fIdentity, 0, 16);

    Matrix.multiplyMM(m_fVPMatrix, 0, m_fViewMatrix, 0, m_fIdentity, 0);
    Matrix.multiplyMM(m_fVPMatrix, 0, m_fProjMatrix, 0, m_fVPMatrix, 0);

    Ray ray = null;
    if (mDeltaX != -99) {
        ray = new Ray(arg0, width, height, mDeltaX, mDeltaY);
    }

    mDeltaX = -99;
    //              Matrix.translateM(m_fVPMatrix, 0, 0, 0, 1);
    GLES20.glUniformMatrix4fv(iVPMatrix, 1, false, m_fVPMatrix, 0);

    GLES20.glDrawElements(GLES20.GL_TRIANGLES, 36, GLES20.GL_UNSIGNED_SHORT, indexBuffer);
    //              GLES20.glDisable(GLES20.GL_TEXTURE_CUBE_MAP);
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Is it possible get which surface of cube will be click in OpenGL?

In a rendering, each object of the scene usually is transformed by the view matrix and the projection matrix. While the view matrix describes the direction and position from which the scene is viewed, the projection matrix describes the mapping from 3D points of a scene, to 2D points of the viewport. The projection matrix transforms from view space to the clip space, and the coordinates in the clip space are transformed to the normalized device coordinates (NDC) in the range (-1, -1, -1) to (1, 1, 1) by dividing with the w component of the clip coordinates.
If a point on a surface of the scene has to be found, by selecting a point on the view port, then a way has to be found to do the opposite.
A common way to identify a surface of an object is to define a ray with a starting point and a direction and to find the surface which is first hit by the ray. The line of sight is such a ray, because it has a start point and a direction, but how to define a ray by the line of sight depends on the projection type of the scene.

While at Orthographic Projection the coordinates in the eye space are linearly mapped to normalized device coordinates, at Perspective Projection the eye space coordinates in the camera frustum (a truncated pyramid) are mapped to a cube (the normalized device coordinates).
In both cases first the viewport position has to be converted to normalize (XY) device coordinates, in the range from (-1,-1) to (1,1). This is a simple linear mapping:

w = with of the viewport
h = height of the viewport
x = X position of the mouse
y = Y position ot the mouse

ndc_x = 2.0 * x/w - 1.0;
ndc_y = 1.0 - 2.0 * y/h; // invert Y axis

Define a line of sight ray at orthographic projection in view space

Orthographic projection

The start point of the ray can be calculated by transforming the point the viewport in normalized device coordinates on the near plane (z = 0), with the inverse projection matrix.

R0_view = inverse( projection-matrix ) * (ndc_x, ndc_y, 0.0, 1.0)

The direction of the line of sight is the direction into the view port (0, 0, -1).

D_view = (0.0, 0.0, -1.0)

Define a line of sight ray at perspective projection in view space

Perspective projection

The start point of the line of sight is the camera position, which is (0, 0, 0) in view space.

R0_view = (0.0, 0.0, 0.0)

The direction of the line of sight can be calculated by transforming any point on the ray in normalized device coordinates, by the inverse projection matrix.

D_view = normalize( inverse( projection-matrix ) * (ndc_x, ndc_y, 0.0, 1.0) )

Convert from view coordinates to world coordinates

To convert from the view space to the world space, the view space coordinates have to be transformed by the inverse view matrix.

R0_world = inverse( view-matrix ) * R0_view
R1_world = inverse( view-matrix ) * (R0_view + D_view)
D_world  = normalize(R1_world - R0_world)

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 intersection 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 contour.

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 A, B and C, the plane can be calculated as follows:

P0 = A
NV = normalize( cross( B-A, C-A ) )

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:

P_isect    = R0 + D * dist_isect
dist_isect = dot( P0 - R0, NV ) / dot( D, NV ) 

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 contour

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 )
} 


The answers to the following questions will be of interest too, to solve the issue:

See the WebGL example, which demonstrate the algorithm:

glArrayType = typeof Float32Array !="undefined" ? Float32Array : ( typeof WebGLFloatArray != "undefined" ? WebGLFloatArray : Array );

function IdentityMat44() {
  var m = new glArrayType(16);
  m[0]  = 1; m[1]  = 0; m[2]  = 0; m[3]  = 0;
  m[4]  = 0; m[5]  = 1; m[6]  = 0; m[7]  = 0;
  m[8]  = 0; m[9]  = 0; m[10] = 1; m[11] = 0;
  m[12] = 0; m[13] = 0; m[14] = 0; m[15] = 1;
  return m;
};

function RotateAxis(matA, angRad, axis) {
    var aMap = [ [1, 2], [2, 0], [0, 1] ];
    var a0 = aMap[axis][0], a1 = aMap[axis][1]; 
    var sinAng = Math.sin(angRad), cosAng = Math.cos(angRad);
    var matB = new glArrayType(16);
    for ( var i = 0; i < 16; ++ i ) matB[i] = matA[i];
    for ( var i = 0; i < 3; ++ i ) {
        matB[a0*4+i] = matA[a0*4+i] * cosAng + matA[a1*4+i] * sinAng;
        matB[a1*4+i] = matA[a0*4+i] * -sinAng + matA[a1*4+i] * cosAng;
    }
    return matB;
}

function Cross( a, b ) { return [ a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0], 0.0 ]; }
function Dot( a, b ) { return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; }
function Normalize( v ) {
    var len = Math.sqrt( v[0] * v[0] + v[1] * v[1] + v[2] * v[2] );
    return [ v[0] / len, v[1] / len, v[2] / len ];
}

function PointInOrOn( P1, P2, A, B )
{
    CP1 = Cross( [ B[0]-A[0], B[1]-A[1], B[2]-A[2] ], [ P1[0]-A[0], P1[1]-A[1], P1[2]-A[2] ] )
    CP2 = Cross( [ B[0]-A[0], B[1]-A[1], B[2]-A[2] ], [ P2[0]-A[0], P2[1]-A[1], P2[2]-A[2] ] )
    return Dot( CP1, CP2 ) >= 0;
}

function PointInOrOnTriangle( P, A, B, C )
{
    var isInA = PointInOrOn( P, A, B, C );
    var isInB = PointInOrOn( P, B, C, A );
    var isInC = PointInOrOn( P, C, A, B );
    return isInA && isInB && isInC;
} 

vec4_add = function( a, b ) { return [ a[0]+b[0], a[1]+b[1], a[2]+b[2], a[3]+b[3] ]; }
vec4_sub = function( a, b ) { return [ a[0]-b[0], a[1]-b[1], a[2]-b[2], a[3]-b[3] ]; }
vec4_mul = function( a, b ) { return [ a[0]*b[0], a[1]*b[1], a[2]*b[2], a[3]*b[3] ]; }
vec4_scale = function( a, s ) { return [ a[0]*s, a[1]*s, a[2]*s, a[3]*s ]; }

mat44_inverse = function( m ) {

    var Coef00 = m[2*4+2] * m[3*4+3] - m[3*4+2] * m[2*4+3];
    var Coef02 = m[1*4+2] * m[3*4+3] - m[3*4+2] * m[1*4+3];
    var Coef03 = m[1*4+2] * m[2*4+3] - m[2*4+2] * m[1*4+3];    
    var Coef04 = m[2*4+1] * m[3*4+3] - m[3*4+1] * m[2*4+3];
    var Coef06 = m[1*4+1] * m[3*4+3] - m[3*4+1] * m[1*4+3];
    var Coef07 = m[1*4+1] * m[2*4+3] - m[2*4+1] * m[1*4+3];   
    var Coef08 = m[2*4+1] * m[3*4+2] - m[3*4+1] * m[2*4+2];
    var Coef10 = m[1*4+1] * m[3*4+2] - m[3*4+1] * m[1*4+2];
    var Coef11 = m[1*4+1] * m[2*4+2] - m[2*4+1] * m[1*4+2];   
    var Coef12 = m[2*4+0] * m[3*4+3] - m[3*4+0] * m[2*4+3];
    var Coef14 = m[1*4+0] * m[3*4+3] - m[3*4+0] * m[1*4+3];
    var Coef15 = m[1*4+0] * m[2*4+3] - m[2*4+0] * m[1*4+3];   
    var Coef16 = m[2*4+0] * m[3*4+2] - m[3*4+0] * m[2*4+2];
    var Coef18 = m[1*4+0] * m[3*4+2] - m[3*4+0] * m[1*4+2];
    var Coef19 = m[1*4+0] * m[2*4+2] - m[2*4+0] * m[1*4+2];   
    var Coef20 = m[2*4+0] * m[3*4+1] - m[3*4+0] * m[2*4+1];
    var Coef22 = m[1*4+0] * m[3*4+1] - m[3*4+0] * m[1*4+1];
    var Coef23 = m[1*4+0] * m[2*4+1] - m[2*4+0] * m[1*4+1];
      
    var Fac0 = [Coef00, Coef00, Coef02, Coef03];
    var Fac1 = [Coef04, Coef04, Coef06, Coef07];
    var Fac2 = [Coef08, Coef08, Coef10, Coef11];
    var Fac3 = [Coef12, Coef12, Coef14, Coef15];
    var Fac4 = [Coef16, Coef16, Coef18, Coef19];
    var Fac5 = [Coef20, Coef20, Coef22, Coef23];
      
    var Vec0 = [ m[1*4+0], m[0*4+0], m[0*4+0], m[0*4+0] ];
    var Vec1 = [ m[1*4+1], m[0*4+1], m[0*4+1], m[0*4+1] ];
    var Vec2 = [ m[1*4+2], m[0*4+2], m[0*4+2], m[0*4+2] ];
    var Vec3 = [ m[1*4+3], m[0*4+3], m[0*4+3], m[0*4+3] ];
      
    var Inv0 = vec4_add( vec4_sub( vec4_mul(Vec1, Fac0), vec4_mul(Vec2, Fac1) ), vec4_mul( Vec3, Fac2 ) );
    var Inv1 = vec4_add( vec4_sub( vec4_mul(Vec0, Fac0), vec4_mul(Vec2, Fac3) ), vec4_mul( Vec3, Fac4 ) );
    var Inv2 = vec4_add( vec4_sub( vec4_mul(Vec0, Fac1), vec4_mul(Vec1, Fac3) ), vec4_mul( Vec3, Fac5 ) );
    var Inv3 = vec4_add( vec4_sub( vec4_mul(Vec0, Fac2), vec4_mul(Vec1, Fac4) ), vec4_mul( Vec2, Fac5 ) );
      
    var SignA = [+1.0, -1.0, +1.0, -1.0];
    var SignB = [-1.0, +1.0, -1.0, +1.0];
    var Inverse = [ vec4_mul(Inv0, SignA), vec4_mul(Inv1, SignB), vec4_mul(Inv2, SignA), vec4_mul(Inv3, SignB) ];
      
    var Row0 = [Inverse[0][0], Inverse[1][0], Inverse[2][0], Inverse[3][0] ];
      
    var Dot0 = [Row0[0], Row0[1], Row0[2], Row0[3] ];
    Dot0

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...