PDA

View Full Version : Specifying translating factor

Mukund
11-16-2010, 07:31 AM
Hello,

i am trying to use IR cameras to move around graphical objects(just a cube) on the screen.
But im not able to get the real world effect, meaning, the cube becomes very small when moved by a certain distance.

Eg: Our hand appear to become small by a certain factor when we move our hands farther(in the real world).

How can i produce the same effect in the virtual world?

Viewing volume:

glFrustum(-500, 500, -500, 500, 100, 2000);

also camera location,

gluLookAt (0, 0, 200.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

Now, i translate the graphic object by a factor of 100 along -Z when the IR source moves 12cm away from the IR camera.

as:

glTranslatef(/* some value */, /*some value */, -z);

But, the object(cube) becomes very small when i do that.
So, how can i adjust the translating factor so that i get the "real world effect" ?

ZbuffeR
11-16-2010, 07:59 AM
Easy !
You have to tweak glFustrum to match your camera intrinsics !

Put your camera on a grid, measure at nearClip distance (100) how much you see to the left and to right, do the same for tom and bottom, and replace the -500,500 values with your actual measurements.

Please, provide some pictures of the results.

EDIT : if you are using a wiimote, read this :
http://www.wiimoteproject.com/wiimote-whiteboard/wiimote-camera-angles/

Mukund
11-16-2010, 09:01 AM
Thanks a lot Zbuffer.

Yes, im using Wiimotes(2 of them to calculate Z)

Well, i do not have a problem with X and Y. Just the Z. For X and Y, im doing this:

glMatrixMode(GL_PROJECTION);
glFrustum(-500, 500, -500, 500, 100, 2000);

glMatrixMode(GL_MODELVIEW);
gluLookAt (0, 0, 200.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

int xDiff = abs(xWiiPos[0] - xWiiPos[1]);
xDiff = (xDiff) ? (xDiff) : (1);

x = (position[0][0] / (double)1024) * 1000;
y = (position[0][1] / (double)768) * 1000;
z = (500 / (double)xDiff) * 100; // translate by 500

/* here, position array is used to store values of X and Ys returned by the IR sources. SO, for IR source 0, position[0][0] will have X and position[0][1] will have Y and so on.

So, im mapping the 0-1024 range to -500 to 500(x axis) and similarly on Y axis.

X and Y are in Wiimote resolution (1024 x 768)

im using the difference in the X positions reported by the 2 Wiimotes to find Z.
*/

So, i basically map the 0 to 1024 range of Wiimote to -500 to 500 in the viewing volume. So, no problem wrt X and Y.

However, the Z is not working fine.

Here are the pics:
The right window is the OpenCV window.Please ignore that. Also, the image in the glut window is inverted(have to fix it yet).

1)Z = 12cm
http://img517.imageshack.us/i/89092453.png/

2)Z = 24cm
http://img708.imageshack.us/i/72351217.png/

3)Z = 36cm
http://img600.imageshack.us/i/51153671.png/

As you can see, the cube becomes very small(doesn't look natural)
How can i fix this?

Mukund
11-16-2010, 09:24 AM
Also, i obtained these values:

Candle size(pixels) Size of cube(in pixels)
Z=12 100x100 100x110
Z=24 58x63 50x50
Z=36 40x30 30x20

Approximate reduction in size:

Candle Cube
First movement : 65% 77%
Second movement: 65% 77%

So, i need a 65% size reduction. So what factor can i translate by?

ZbuffeR
11-16-2010, 11:51 AM
Obviously you do not understand basic principles of 3D projection.
Re-read my post above, then follow its instructions, then try to understand why it works, then come back if you have further questions.

Mukund
11-16-2010, 12:42 PM
Thanks!

Could you please explain what i was doing wrong? i did read your post, and i did not quite get what you meant by putting the camera on a grid and measuring.

And, since i was getting the result for the x and y axes, i assumed my method was right and i thought of trying for Z.

i used a library that returns values 0-1024 for the IR source in the X direction. i was mapping these values to obtain values from -500 to 500 and use it to move the graphical cube on the screen.

It would be really helpful if you could please point out my mistake.

ZbuffeR
11-16-2010, 01:34 PM
1)
Ok forget the grid.
Assuming your units are in millimeters, put two candles (C1 and C2) 1000 mm apart (500 minus -500), aim your wiimote right between the candles (middle point M). Then move the wiimote until each candle touches an edge. Now measure distance D between wiimote and point M.
Change frustum like this :
glFrustum(-500, 500, -500, 500, D, far);
You should now have real world values for x,y,z in millimeters.

Do you understand what we did here ?

2) Now for a more practical frustum, let's multiply all that by minimumDistance/D :
glFrustum(-500*minDist/D, 500*minDist/D, -500*minDist/D, 500*minDist/D, minDist, farEnough);

Still good ?

3) NOW WHY YOU MIX 2D PROJECTION COORDINATES (0-1024) WITH 3D WORLD COORDINATES ?
3D is not "lets keep projected x,y and just add z".
When you get X=1024 from your IR lib, it can mean world x=5 for z=10, and x=10 for z=20

Okay ?

So, what to do you have to do, when you know world z, to convert projected x,y to world x,y ? Try to at least find this yourself.

Mukund
11-16-2010, 01:47 PM
Thanks again ZBuffer.

i think you got me wrong. i am using 2 Wiimotes to get the Z from a single IR source.

So, i used a method to find the Z. i use the difference between the X values reported by the Wiimotes to find at what Z distance from the Wiimote the IR source is.

Mukund
11-16-2010, 02:04 PM
Ah, i think i get it. i understood the part about setting up the viewing volume.

Now, using the two Wiimotes, i obtain Z in terms of world. After that, if i have set up the camera right, i will get the proper result when i move the IR source in the Z direction right?

>>So, what to do you have to do, when you know world z, to convert projected x,y to world x,y ? Try to at least find this yourself.

Well, i am currently obtaining the world x,y and using glTranslatef(), i place the object.

Is that fine?

Thanks for the support.

ZbuffeR
11-16-2010, 02:09 PM
How do you get world x,y exactly ?

Mukund
11-16-2010, 02:32 PM
i use the values returned by the Wiimote library. then convert it into world x,y.

ie the wiimote returns 0-1024,

((xReturned / 1024 * 1000) - 500) gives me the world X.

Similary for y also.

Then i translate the object by these values. Is this correct?

ZbuffeR
11-16-2010, 02:49 PM
no as I tried to explain in point 3

But go ahead, you have to experiment to learn.

Mukund
11-16-2010, 03:05 PM
Hmm, guess i did not follow :(.

Well, thanks anyway, i will read your post again, and try doing it again.

Thanks a lot for the support.

Mukund
11-20-2010, 04:09 AM
Hello ZBuffer,

i followed your suggestions and i obtained the following results.

The candles were separated by a distance of 1280mm, and i got the near clip plane(D) as 1600.

Now,

glFrustum(-640, 640, -480, 480, 1600, 20000);

amd the camera is placed as:

gluLookAt (0, 0, 2000.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
This is how i obtain real world x, y:

The IR camera has 33 and 26 degrees FOV.

double zPos = realZPos; // Z distance in mm
double tempX = zPos * tan(16.5 * (3.14 / 180));
double tempY = zPos * tan(13.0 * (3.14 / 180));
x = (position[0][0] / (double)1024) * (tempX * 2);
y = (position[0][1] / (double)768) * (tempY * 2);

position[0][1] and position[0][0] have the X and Y values returned by the IR library.

here is the calculations i did

http://img99.imageshack.us/i/sampb.png/

Now that i have found x and y, i can translate the object. Have i got it correct now?

Please excuse me if this sounds trivial, i had a course in Computer Graphics and i guess i did not get my basics right. So, im trying to learn now.

Thanks.

ZbuffeR
11-20-2010, 04:14 PM
This looks much better.
How go you get realZPos by the way ? Is that a given, or a measure you get from something ?

Mukund
11-20-2010, 10:46 PM
im using 2 Wiimotes for that. i needed to track a single source(track Z too), which i was not able to do using a single Wiimote.

So, using 2 Wiimotes, the difference of X reported by the Wiimotes is noted. If the IR source goes far, the difference between the reported X(ie the difference between the X values reported by the Wiimotes) becomes less.

i did it on an experimental basis.

ie
if Difference between Xs is around 500, then Z = 2500mm
if Difference between Xs is around 200, then Z = 5000mm
and so on,

This was done on an experimental basis. Right now, im able to measure upto 12500mm from the two Wiimotes.

So, the real world x and y are obtained using this.

double tempX = zPos * tan(16.5 * (3.14 / 180));

So, the zPos here is the measured Z.

So, i need to translate my object based on these x, y, z obtained.

Please correct me if i have gone wrong in any of the steps.