# Wiimote Project

## Wiimote Projects => Wiimote Desktop VR/Head Tracking => Topic started by: tarantula78 on February 26, 2008, 03:00:13 PM

Title: Explanation of Source Code
Post by: tarantula78 on February 26, 2008, 03:00:13 PM
Hi all,

Im pretty average at maths but there was one part of the code that I didnt understand and that is how the distance from the TV/Monitor is calculated.

I gathered that this part of the code was relied on:

Line 261:

double angle = Math.Acos(.5 / headDist)-Math.PI / 2;//angle of head to screen

Line 777:
headDist = movementScaling * (float)((dotDistanceInMM / 2) / Math.Tan(angle)) / screenHeightinMM;

If anyone could explain why it is 0.5 that is being divided and how it is calculated.

Thanks
Title: Re: Explanation of Source Code
Post by: tarantula78 on February 27, 2008, 01:30:34 PM
ok, sincere apologies to everyone thats not the code i needed help with its the wrong one >.<

Quote
float angle = radiansPerPixel * pointDist / 2;
//in units of screen hieght since the box is a unit cube and box hieght is 1
headDist = movementScaling * (float)((dotDistanceInMM / 2) / Math.Tan(angle)) / screenHeightinMM;

float avgX = (firstPoint.x + secondPoint.x) / 2.0f;
float avgY = (firstPoint.y + secondPoint.y) / 2.0f;

//should  calaculate based on distance

relativeVerticalAngle = (avgY - 384) * radiansPerPixel;//relative angle to camera axis

if(cameraIsAboveScreen)
else
}

the lines i need explained are highlighted

in the first line: why is it divided by 2? is it because the triangle that is formed is divided to make a right angle triangle?

the second line: what is the significance of dividing the dot distance with the Tangent of the angle retrieved?

in the third and fourth could someone just give me a general explanation of whats going on.

Tarantula
Title: Re: Explanation of Source Code
Post by: Wilco on April 22, 2008, 07:02:54 AM

(http://www.wilco.ismysite.co.uk/Geometry.GIF)

we know the actual length of the top side, as it dotDistanceInMM.
From the first line we know the angle (each pixel on the camera in the wiimote represents a set amount of angle).

This is a isoceles triangle, so dividing both by 2 gives us a right angle triangle, the white area in the picture. Pythagorean rules for right angle triangles define

or in our variable terms

the other 2 terms (confusingly 1 at the start and 1 at the end) are just scaling factors, the first allows use to exaggerate all movement if we want to, and the second normalises by the size of the screen. Not totally sure about this bit, it means if you have a large screen everything seems bigger, bit if you have your head in the same place you see the same thing (as opposed to be being able to see more)

3) combines a few operations into 1 line of code. So working outwards from the middle:

avgX is the midpoint of the head from the far left of the camera
avg-512 is the midpoint of the head, with 0 being right in the centre of the screen. -ve 1 side and +ve the other.

radiansPerPixel * (avgX - 512) = the angle of the centre of the head from the centerline of the camera, so again -ve angle is on 1 side and +ve on the other.

Now we construct a very similar triangle to last time:
(http://www.wilco.ismysite.co.uk/Geometry2.GIF)

Sin(angle) = opposite / hypotenuse

rearranging:

again add in the movementScaling term to allow exaggeration.

headY requires a bit more, as we dont assume the camera is horizontal (but we did assume it was perpedicular to the screen for headX).Also it needs to take into account being above or below the screen (again for X we assumed the wiimote was in the middle of the screen).

so we add on cameraVerticaleAngle (nicely misspelt).

and then add or subtract 0.5 depending on where the camera is.

Why 0.5? because ever since we "/screenHeightinMM" in 2) we have been work in terms of screen heights. so headX would say "head is 1 screen height left" and headY would say "head is 0.7 screen heights up". So if the camera is half a screen height above the TV we need to subtract 0.5 to move to the middle of the TV.

Title: Re: Explanation of Source Code
Post by: yashardel on January 27, 2009, 06:28:34 AM
Hi!

To Wilco:
Thanks man! That explanation really helped!

But I have querstion too. If you have the sketch of Horizontal and Vertical Position in front of you, would see
that headDist is different in two positions but why they are used as being similar! I guessit is a mistake unless I am ignoring something! The relation is as below:

Can you help me?!
Title: Re: Explanation of Source Code
Post by: yashardel on January 27, 2009, 06:38:25 AM
By the way, when the camera is above the acreen 0.5f is added not subtracted!?You know why!?

if(cameraIsAboveScreen)
Title: Re: Explanation of Source Code
Post by: ministe2003 on February 26, 2009, 10:36:41 AM
Thanks from me too for that, helped a lot.

I have a question, early in that maths Johnny calculates the distance between the two dots as follows (code is c++ and using a different library so will be different to Johnny's but the maths is the same):

float dx = firstPoint->GetX() - secondPoint->GetX();
float dy = firstPoint->GetY() - secondPoint->GetY();
float pointDist = (float)sqrt(dx * dx + dy * dy);

This gives us the distance between the two points.

Why then, do we also need to manually give the width of our sensor bar in the form of dotDistanceInMM?

In addition, why is avgX - 512 the midpoint of the head?  Is it because the camera is 1024 wide?

Cheers
Title: Re: Explanation of Source Code
Post by: ministe2003 on March 05, 2009, 10:10:36 AM
In addition, in your diagrams you show headDist as at one stage being the Adjacent and in the next, the Hypotenuse... this isn't right surely?  The value of headDist isn't changed between these two diagrams so how can the one value possibly be used to represent two different length sides?

Thanks
Title: Re: Explanation of Source Code
Post by: spectre1989 on May 02, 2009, 12:11:24 AM
Cheers for the explanation, cleared things up a bit. I actually went ahead and did things differently and worked out the head distance based on the fact you know how wide the sensor bar is in reality, and you know how wide it looks to the wiimote camera, so from that you can work out how far away it is, using the inverse of 3D projection.

Whereas normally you would have:
Code: [Select]
`point2D.x = (znear*point3D.x)/point3D.z;point2D.y = (znear*point3D.y)/point3D.z;`Solving for z gives:
Code: [Select]
`z = (znear*x3D)/x2D;// or in this casez = (znear*widthReal)/widthOnCamera;`It actually didn't occur to me to do the radians per pixel, thinking about it that's a much more logical idea.. There's something about messing with 3D to 2D projections (and vice versa) which instantly makes me start picturing a buttload of right angle triangles!
Title: Re: Explanation of Source Code
Post by: wiicool on July 23, 2010, 03:28:31 PM
hey people :)
I'm sorry that I'm taking this old topic up again.
But I still don't get this:

Code: [Select]
`                if(cameraIsAboveScreen)                    headY = .5f+(float)(movementScaling * Math.Sin(relativeVerticalAngle + cameraVerticaleAngle)  *headDist);                else                    headY = -.5f + (float)(movementScaling * Math.Sin(relativeVerticalAngle + cameraVerticaleAngle) * headDist);            }`
Quote
and then add or subtract 0.5 depending on where the camera is.

Why 0.5? because ever since we "/screenHeightinMM" in 2) we have been work in terms of screen heights. so headX would say "head is 1 screen height left" and headY would say "head is 0.7 screen heights up". So if the camera is half a screen height above the TV we need to subtract 0.5 to move to the middle of the TV.

But the opposite is done: if the camera is above screen 0.5 is added. Why this? I'd be very happy if someone could explain that to me ;)

Greets