Specifying translating factor


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.


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” ?

Can anyone please help?
Thanks in advance.

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 :

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:

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

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

2)Z = 24cm

3)Z = 36cm

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

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?

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.


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.

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 ?

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

Still good ?

    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.

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.

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.

How do you get world x,y exactly ?

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?

no as I tried to explain in point 3

But go ahead, you have to experiment to learn.

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.

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.


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


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.


This looks much better.
How go you get realZPos by the way ? Is that a given, or a measure you get from something ?

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.

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.