Log in or register to post comments

Touch event on 3d object in object recognition

August 28, 2017 - 1:15am #1

Hi,

I am showing multiple 3d objects when detecting object target not image target. I want to detect touch event on 3d object i.e. which object is tapped among multiple 3d objects. I used dominoes 3d object vertices, texcords and normals and dominoes example methods.

My method to show multiple 3d objects is below,

- (void)renderFrameWithState:(const Vuforia::State &)state projectMatrix:(Vuforia::Matrix44F &)projectionMatrix

{

    [self setFramebuffer];

    // Render video background

    [sampleAppRenderer renderVideoBackground];

   glEnable(GL_DEPTH_TEST);

    glDisable(GL_CULL_FACE);

    glEnable(GL_BLEND);

    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    glCullFace(GL_BACK);

   currentProjectionMatrixx = projectionMatrix;

    for (int i = 0; i < state.getNumTrackableResults(); ++i) {

        // Get the trackable

        const Vuforia::TrackableResult* result = state.getTrackableResult(i);

        const Vuforia::Trackable& trackable = result->getTrackable();

       if (! result->isOfType(Vuforia::ObjectTargetResult::getClassType())) {

            continue;\ }

        modelViewMatrixx = Vuforia::Tool::convertPose2GLMatrix(result->getPose());

        NSLog(@"@>@ ObjectTarget found!");

       const Vuforia::ObjectTarget& objectTarget = (const Vuforia::ObjectTarget&) trackable;

       Vuforia::Vec3F objectSize = objectTarget.getSize();

        // OpenGL 2

        Vuforia::Matrix44F modelViewProjection;

        for (int j = 0; j<3; j++) {

            float x;

            float y;

            float z;

            float scale = 10;

               if (j == 0) {

                    x = 90;

                    y = 20;

                    z = 50;

                }else if (j == 1) {

                    x = 40;

                    y = 120;

                    z = 50;

                }else if (j == 2){

                    x = 140;

                    y = 200;

                    z = 50;

                }

            Vuforia::Matrix44F modelViewMatrix = Vuforia::Tool::convertPose2GLMatrix(result->getPose());

            SampleApplicationUtils::rotatePoseMatrix(90, 1, 1, 1,&modelViewMatrix.data[0]);

            if (!isClicked) {

                // Set GL20 flags

                glEnableVertexAttribArray(vertexHandle);

                glEnableVertexAttribArray(normalHandle);

                glEnableVertexAttribArray(textureCoordHandle);

                glVertexAttribPointer(vertexHandle, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid*) &cubeVertices[0]);

                glVertexAttribPointer(normalHandle, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid*) &cubeNormals[0]);

                glVertexAttribPointer(textureCoordHandle, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid*) &cubeTexCoords[0]);

                Vuforia::Matrix44F transform = SampleMath::Matrix44FIdentity();

                float* transformPtr = &transform.data[0];

                SampleApplicationUtils::translatePoseMatrix(x, y, z, &modelViewMatrix.data[0]);

                SampleApplicationUtils::rotatePoseMatrix(90, 0, 1, 0,&modelViewMatrix.data[0]);

                SampleApplicationUtils::scalePoseMatrix(10.0, 10.0, 10.0f, &modelViewMatrix.data[0]);

                // Render a cube with the given transform

               // Assumes prior GL setup

               Vuforia::Matrix44F modelViewProjection, objectMatrix;

                SampleApplicationUtils::multiplyMatrix(&modelViewMatrix.data[0], transformPtr, &objectMatrix.data[0]);

               SampleApplicationUtils::multiplyMatrix(&currentProjectionMatrixx.data[0], &objectMatrix.data[0], &modelViewProjection.data[0]);

               glBindTexture(GL_TEXTURE_2D, augmentationTexture[2].textureID);

                glUniformMatrix4fv(mvpMatrixHandle, 1, GL_FALSE, (GLfloat*)&modelViewProjection.data[0]);

                glUniform1i(texSampler2DHandle, 0 /*GL_TEXTURE0*/);

                glDrawElements(GL_TRIANGLES, NUM_CUBE_INDEX, GL_UNSIGNED_SHORT, (const GLvoid*) &cubeIndices[0]);

                matrixArray[j] = modelViewMatrix;

   

            }

    glDisableVertexAttribArray(vertexHandle);

    glDisableVertexAttribArray(normalHandle);

    glDisableVertexAttribArray(textureCoordHandle);

    glDisable(GL_DEPTH_TEST);

    glDisable(GL_BLEND);

    glDisable(GL_CULL_FACE);

 

    [self presentFramebuffer];

 

}

Dominoes methods used are below,

void

projectScreenPointToPlanee(Vuforia::Vec2F point, Vuforia::Vec3F planeCenter, Vuforia::Vec3F planeNormal,

                           Vuforia::Vec3F &intersection, Vuforia::Vec3F &lineStart, Vuforia::Vec3F &lineEnd)

{

    Vuforiautils *vUtils = [Vuforiautils getInstance];

 

    // Window Coordinates to Normalized Device Coordinates

    Vuforia::VideoBackgroundConfig config = Vuforia::Renderer::getInstance().getVideoBackgroundConfig();

    float halfScreenWidth = vUtils.viewSize.height / 2.0f; // note use of height for width

    float halfScreenHeight = vUtils.viewSize.width / 2.0f; // likewise

 

    float halfViewportWidth = config.mSize.data[0] / 2.0f;

    float halfViewportHeight = config.mSize.data[1] / 2.0f;

    float x = (vUtils.contentScalingFactor * point.data[0] - halfScreenWidth) / halfViewportWidth;

    float y = (vUtils.contentScalingFactor * point.data[1] - halfScreenHeight) / halfViewportHeight * -1;

 

    Vuforia::Vec4F ndcNear(x, y, -1, 1);

    Vuforia::Vec4F ndcFar(x, y, 1, 1);

    // Normalized Device Coordinates to Eye Coordinates

    Vuforia::Matrix44F projectionMatrix = currentProjectionMatrixx;

    Vuforia::Matrix44F inverseProjMatrix = SampleMath::Matrix44FInverse(projectionMatrix);

    Vuforia::Vec4F pointOnNearPlane = SampleMath::Vec4FTransform(ndcNear, inverseProjMatrix);

    Vuforia::Vec4F pointOnFarPlane = SampleMath::Vec4FTransform(ndcFar, inverseProjMatrix);

    pointOnNearPlane = SampleMath::Vec4FDiv(pointOnNearPlane, pointOnNearPlane.data[3]);

    pointOnFarPlane = SampleMath::Vec4FDiv(pointOnFarPlane, pointOnFarPlane.data[3]);

 

    // Eye Coordinates to Object Coordinates

    Vuforia::Matrix44F inverseModelViewMatrix = SampleMath::Matrix44FInverse(modelViewMatrixx);

    Vuforia::Vec4F nearWorld = SampleMath::Vec4FTransform(pointOnNearPlane, inverseModelViewMatrix);

    Vuforia::Vec4F farWorld = SampleMath::Vec4FTransform(pointOnFarPlane, inverseModelViewMatrix);

 

    lineStart = Vuforia::Vec3F(nearWorld.data[0], nearWorld.data[1], nearWorld.data[2]);

    lineEnd = Vuforia::Vec3F(farWorld.data[0], farWorld.data[1], farWorld.data[2]);

    linePlaneIntersectionn(lineStart, lineEnd, planeCenter, planeNormal, intersection);

}

bool

linePlaneIntersectionn(Vuforia::Vec3F lineStart, Vuforia::Vec3F lineEnd,

                       Vuforia::Vec3F pointOnPlane, Vuforia::Vec3F planeNormal,

                       Vuforia::Vec3F &intersection)

{

    Vuforia::Vec3F lineDir = SampleMath::Vec3FSub(lineEnd, lineStart);

    lineDir = SampleMath::Vec3FNormalize(lineDir);

 

    Vuforia::Vec3F planeDir = SampleMath::Vec3FSub(pointOnPlane, lineStart);

 

    float n = SampleMath::Vec3FDot(planeNormal, planeDir);

    float d = SampleMath::Vec3FDot(planeNormal, lineDir);

    if (fabs(d) < 0.00001) {

        // Line is parallel to plane

        return false;

    }

 

    float dist = n / d;

 

    Vuforia::Vec3F offset = SampleMath::Vec3FScale(lineDir, dist);

    intersection = SampleMath::Vec3FAdd(lineStart, offset);

    return true;

}

 

Method used to detect touch event is below,

// Pass touch events through to the Dominoes module

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

{

        UITouch* touch = [touches anyObject];

        CGPoint location = [touch locationInView:self];

        dominoesTouchEvent(ACTION_DOWN, 0, location.x, location.y);

        NSLog(@"location - x(%f) y(%f)",location.x, location.y);

        Vuforia::Vec3F intersection, lineStart, lineEnd;

        projectScreenPointToPlanee(Vuforia::Vec2F(location.x, location.y), Vuforia::Vec3F(0, 0, 0), Vuforia::Vec3F(0, 0, 1), intersection, lineStart, lineEnd);

    

            Vuforia::Matrix44F transform = SampleMath::Matrix44FIdentity();

            float* transformPtr = &transform.data[0];

            SampleApplicationUtils::translatePoseMatrix(40, 120, 50, transformPtr);

        SampleApplicationUtils::rotatePoseMatrix(90, 0, 1, 0,transformPtr);

    

        SampleApplicationUtils::scalePoseMatrix(10.0, 10.0, 10.0f, transformPtr);

    

            bool hit = checkIntersectionLine(transform, lineStart, lineEnd);

            if (hit)

            {

                // tap touched the object

                NSLog(@"location - x(%f) y(%f)",location.x, location.y);

            }

  }

According to my knowledge bool 'hit' should be true when i touch second 3d object. Because i gave here translate pose matrix of second 3d object.

But Problem is bool is always true wherever i touched on screen not only on 3d objects.

Please help me to detect tap when 3d object is tapped

Log in or register to post comments