Log in or register to post comments

Understanding getPose function

March 4, 2011 - 4:40am #1

Hi all,

I'm very new to Android and to QCAR, so please bare with me.

I'm trying to display 2D image on the tracked image. I can get the screenPoint and display image on the screen by using QCAR::Vec2F screenPoint = QCAR::Tool::projectPoint(cameraCalibration, trackable->getPose(), QCAR::Vec3F(0, 0, 0));

I need also to scale & rotate the 2D image, so I think getPose function on trackable object can be the solution. Can someone explain the values in 3*4 matrix that getPose function returns? Are they x, y, z, u, v etc?

Thanks in advance
Oz

Understanding getPose function

August 30, 2012 - 10:16am #22

Also make sure that you're loading the new texture. Which SDK are you using?

Understanding getPose function

August 30, 2012 - 3:02am #21

What are the dimensions of your texture?

They need to be a power of 2 in size e.g. 256*256 pixels

N

i have used sample app and replaced teapot image with custom ima

August 30, 2012 - 12:13am #20

i have used sample app and replaced teapot image with custom image but now am not getting texture in my 3d image it is displaying black, I am not getting why it is happening lik this, why texture is not getting any idea???. Thanks in advance..

i have used sample app and replaced teapot image with custom ima

August 30, 2012 - 12:12am #19

i have used sample app and replaced teapot image with custom image but now am not getting texture in my 3d image it is displaying black, I am not getting why it is happening lik this, why texture is not getting any idea???. Thanks in advance..

Re: Understanding getPose function

January 29, 2012 - 8:09pm #18

@ ozayolkan, Omen_20, tsengvn, gilesian, and lhslktg.

Guys, why don't you use the Unity3d game engine for all of this? It is really easy to use, QCAR integrates very nicely with it, and it will save you a lot of time.

Re: Understanding getPose function

January 29, 2012 - 9:29am #17

That code would go just before you render your textured plane. Look for similar calls to glEnable in the renderFrame method. Also make sure you disable blending at the end of the function:

glDisable(GL_BLEND);

Again, this method assumes you've preprocessed all of your images to make them a power-of-two by padding them with transparent pixels.

- Kim

Re: Understanding getPose function

January 26, 2012 - 8:28pm #16

Many devices do not support non-power-of-two (NPOT) textures. This is a hardware limitation.

You can stretch your image to a power-of-two (POT) and then render it on a plane of the correct dimensions. This will "undo" the stretch so the final image looks correct.

Another option is to write your own Texture class that places your NPOT image in the next closest POT texture. So for your 200x512 image it would create a 256x512 texture and place the image in one corner of the texture. Then you have to adjust the texcoords of your model to match. This is more advanced.

Or, if you really don't want to change the rendering code per image, you could pad out each image with transparent pixels to make it a POT. E.g. create a 256x512 canvas with a transparent background and place your image in the center. Then use OpenGL blending to hide the transparent border:

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

That's a little less efficient, but your code won't need to know the original image size.

- Kim

Re: Understanding getPose function

January 25, 2012 - 7:22pm #15
Quote:

And even I use same dimensional, it also show whole black.

That was going to be my first guess... Make sure the images are 1024x1024 or smaller, and it's safest to use power-of-two dimensions (e.g. 128, 256, 512, 1024).

Maybe the images were saved with a strange color profile? Could you attach one here, or send to

?

- Kim

Re: Understanding getPose function

January 24, 2012 - 8:28pm #14

If you look through the renderFrame method you should find a chunk of code that looks like this:

QCAR::Matrix44F modelViewProjection;

SampleUtils::translatePoseMatrix(0.0f, 0.0f, kObjectScale,
                                 &modelViewMatrix.data[0]);
SampleUtils::scalePoseMatrix(kObjectScale, kObjectScale, kObjectScale,
                             &modelViewMatrix.data[0]);
SampleUtils::multiplyMatrix(&projectionMatrix.data[0],
                            &modelViewMatrix.data[0] ,
                            &modelViewProjection.data[0]);

glUseProgram(shaderProgramID);
 
glVertexAttribPointer(vertexHandle, 3, GL_FLOAT, GL_FALSE, 0,
                      (const GLvoid*) &teapotVertices[0]);
glVertexAttribPointer(normalHandle, 3, GL_FLOAT, GL_FALSE, 0,
                      (const GLvoid*) &teapotNormals[0]);
glVertexAttribPointer(textureCoordHandle, 2, GL_FLOAT, GL_FALSE, 0,
                      (const GLvoid*) &teapotTexCoords[0]);

glEnableVertexAttribArray(vertexHandle);
glEnableVertexAttribArray(normalHandle);
glEnableVertexAttribArray(textureCoordHandle);

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, thisTexture->mTextureID);
glUniformMatrix4fv(mvpMatrixHandle, 1, GL_FALSE,
                   (GLfloat*)&modelViewProjection.data[0] );
glDrawElements(GL_TRIANGLES, NUM_TEAPOT_OBJECT_INDEX, GL_UNSIGNED_SHORT,
               (const GLvoid*) &teapotIndices[0]);

That is the "OpenGL ES 2.0 rendering code." It is the same for QCAR 1.0 and 1.5. Replace only that part with the code from my post.

- Kim

Re: Understanding getPose function

October 27, 2011 - 6:55am #13

Try adding an include:

#include <QCAR/ImageTarget.h>

- Kim

Re: Understanding getPose function

October 27, 2011 - 2:24am #12

hi kim,

I want to show 3d object model size such that it will cover entire target marker, for that i need widht and height of marker, I found this code snippet for getting size

QCAR::Vec2F targetSize = ((QCAR::ImageTarget *) trackable)->getSize()

but it is not compiling , it is showing error that:

error: 'ImageTarget' is not a member of 'QCAR'

Re: Understanding getPose function

June 7, 2011 - 8:00pm #11

Ah, sorry, it looks like only glColor4f is supported in OpenGL ES:

http://www.khronos.org/opengles/sdk/1.1/docs/man/glColor.xml

- Kim

Re: Understanding getPose function

June 7, 2011 - 7:08pm #10

It still raise an same error after i set USE_OPENGL_ES_1_1 := true and move glColor3f into the code use for drawing in opengl 1.1

Here is the code, can you take a look :

#ifdef USE_OPENGL_ES_1_1
        // Load projection matrix:
        glMatrixMode(GL_PROJECTION);
        glLoadMatrixf(projectionMatrix.data);

        // Load model view matrix:
        glMatrixMode(GL_MODELVIEW);
        glLoadMatrixf(modelViewMatrix.data);

        // Draw object:
      	
	glColor3f(1.0f,1.0f,1.0f);
	QCAR::Vec2F targetSize = ((QCAR::ImageTarget *) trackable)->getSize();
		
	glTranslatef(0.f, 0.f, kObjectScale);
        glScalef(targetSize.data[0], targetSize.data[1], 1.0f);
		
		
		
	glTexCoordPointer(2, GL_FLOAT, 0, (const GLvoid*) &planeTexcoords[0]);
        glVertexPointer(3, GL_FLOAT, 0, (const GLvoid*) &planeVertices[0]);
        glNormalPointer(GL_FLOAT, 0,  (const GLvoid*) &planeNormals[0]);
		
	glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT,  (const GLvoid*) &planeIndices[0]);
        
#else

Thanks

Re: Understanding getPose function

June 7, 2011 - 6:22am #9

glColor3f is only available in OpenGL ES 1.x. You can switch the application to compile against the 1.1 libraries by setting the USE_OPENGL_ES_1_1 flag in Android.mk to true. The ImageTargets sample includes rendering code for both the 1.1 and 2.0 versions of OpenGL.

- Kim

Re: Understanding getPose function

June 6, 2011 - 9:34am #8

Hi Kim,

Your answer is very helpful for me, newbie to openGL. I still have a question, if i dont like to use texture, i want to draw with the defined color, how can i do that ?

I try to comment the line :
glBindTexture(GL_TEXTURE_2D, thisTexture->mTextureID);
and add
glColor3f(1.0,1.0,1.0);

But i seem not work, it raise an error

C:/Development/Android/qcar-sdk-1-0-0/samples/ImageTargets/jni/ImageTargets.cpp:
485: error: 'glColor3f' was not declared in this scope

Re: Understanding getPose function

April 24, 2011 - 12:51am #7

I'm still trying to figure out how to get the center of each trackable for comparison purposes and to draw lines between each. I want to apply a tour algorithm to it.

Edit:
I found the solution by another thread Kim answered.
http://ar.qualcomm.at/node/2000311

I keep finding answers from her threads, it just takes research in OpenGL to understand exactly what it is I want, so that I know what to search for. Hopefully a lot of her answers and work get put into the documentation as some point.

Re: Understanding getPose function

March 4, 2011 - 7:08am #6

The pose is a 3D orientation matrix, analogous to the modelview matrix in OpenGL. It is used alongside the projection matrix to bring 3D world coordinates to screen coordinates. For a full look at the set of transformations involved, see the OpenGL FAQ (section 9.011): http://www.opengl.org/resources/faq/technical/transformations.htm

The pose is a 3D transformation, which means you won't easily get a set of 2D transformations out of it for manipulating 2D images on the screen (you're missing a dimension to rotate in). Instead, I would suggest rendering your image on a 3D plane using OpenGL. It's pretty easy, here are the steps:

1) Start with the ImageTargets sample project. Open ImageTargets.cpp, located in the jni folder.

2) Add the following just after the includes at the top:

#include <QCAR/ImageTarget.h>

static const float planeVertices[] =
{
    -0.5, -0.5, 0.0, 0.5, -0.5, 0.0, 0.5, 0.5, 0.0, -0.5, 0.5, 0.0,
};

static const float planeTexcoords[] =
{
    0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0
};

static const float planeNormals[] =
{
    0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0
};

static const unsigned short planeIndices[] =
{
    0, 1, 2, 0, 2, 3
};

3) Now replace the OpenGL ES 2.0 rendering code in the renderFrame method with the following:

// assuming this is an image target
QCAR::Vec2F targetSize = ((QCAR::ImageTarget *) trackable)->getSize();

QCAR::Matrix44F modelViewProjection;

SampleUtils::translatePoseMatrix(0.0f, 0.0f, kObjectScale,
                                 &modelViewMatrix.data[0]);
SampleUtils::scalePoseMatrix(targetSize.data[0], targetSize.data[1], 1.0f,
                             &modelViewMatrix.data[0]);
SampleUtils::multiplyMatrix(&projectionMatrix.data[0],
                            &modelViewMatrix.data[0] ,
                            &modelViewProjection.data[0]);

glUseProgram(shaderProgramID);
 
glVertexAttribPointer(vertexHandle, 3, GL_FLOAT, GL_FALSE, 0,
                      (const GLvoid*) &planeVertices[0]);
glVertexAttribPointer(normalHandle, 3, GL_FLOAT, GL_FALSE, 0,
                      (const GLvoid*) &planeNormals[0]);
glVertexAttribPointer(textureCoordHandle, 2, GL_FLOAT, GL_FALSE, 0,
                      (const GLvoid*) &planeTexcoords[0]);

glEnableVertexAttribArray(vertexHandle);
glEnableVertexAttribArray(normalHandle);
glEnableVertexAttribArray(textureCoordHandle);

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, thisTexture->mTextureID);
glUniformMatrix4fv(mvpMatrixHandle, 1, GL_FALSE,
                   (GLfloat*)&modelViewProjection.data[0] );
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT,
               (const GLvoid*) &planeIndices[0]);

4) Build the native code using ndk-build, then refresh the Eclipse project and run the app. You should see the teapot texture stretched over the image target.

5) You can swap the texture by adding your image to the project's assets folder (png or jpg format). Then open ImageTargets.java and replace the teapot texture filenames with your own.

Let me know if you have any questions!

- Kim

Log in or register to post comments