Why there's DRIFT/SHIFT after 3D to 2D projection?

A place for users of OGRE to discuss ideas and experiences of utilitising OGRE in their games / demos / applications.
bensvage
Gnoblar
Posts: 1
Joined: Fri Jan 22, 2016 9:30 pm

Why there's DRIFT/SHIFT after 3D to 2D projection?

Post by bensvage »

Hi, I'm trying to get 2D projections of some points. But the result seems not correct. Here's what I got:
1.jpg
2.jpg
I just screenshotted the red points (the skeleton joints of the hand) and the hand. So the red points are actually the 2d images of 3D points while the blue points are 2D projected points I got from the red points.
Therefore, in my opinion, red points and blue points should be at the same position in 2D because they are both the projection of the hand skeleton joints, the red one is got from screenshot while the blue one from calculation. But there remains a drift between the red and blue can I know why?

In this project, I used two cameras. Each of them attached by one viewport. And I created two renderwindow for each camera. The code for how I created the camera and viewport is shown below:

Code: Select all

void HandFrameListener::createScene()
{	// camera
	_camera1 = _scenemanager->createCamera("Camera1");
	_camera2 = _scenemanager->createCamera("Camera2");

	_camera1->setPosition(Ogre::Vector3(-3.35f, 0.f, 20.f));
	_camera2->setPosition(Ogre::Vector3(3.35f, 0.0f, 20));

	_camera1->setFOVy(Radian(atan(240 / 236.f) * 2.f));
	_camera2->setFOVy(Radian(atan(240 / 236.f) * 2.f));

	_camera1->lookAt(Ogre::Vector3(-3.35f, 0.0f, -1.0f)); // 0, 0, -1 original
	_camera1->setNearClipDistance(0.1);
	//_camera1->setFarClipDistance(20);
	_camera2->lookAt(Ogre::Vector3(3.35f, 0.0f, -1.0f));
	_camera2->setNearClipDistance(0.1);
	//_camera2->setFarClipDistance(20);

	// viewport
	Viewport *viewport = _window->addViewport(_camera1);
	viewport->setBackgroundColour(ColourValue(0.0f, 0.0f, 0.0f));

	Viewport *viewportR = _windowR->addViewport(_camera2);
	viewportR->setBackgroundColour(ColourValue(0.f, 0.f, 0.f));

        // I also tried to use this piece of code below, no use; 
	/*Real r = Real(viewport->getActualWidth()) / Real(viewport->getActualHeight()); // I also tried _window->getwidth/_window->getheight, no use
	_camera1->setAspectRatio(r);*/
	/*Real r1 = Real(_window->getWidth() / _window->getHeight());
	_camera1->setAspectRatio(r1);
	Real r2 = Real(_windowR->getWidth() / _windowR->getHeight());
	_camera2->setAspectRatio(r2);*/
}
The code of projection is like this:

Code: Select all

void worldCoordToScreen(Vector3 objPos, Camera* cam, Vector2 screenRect, Vector2& screenPos)
{	Matrix4 viewMatrix = cam->getViewMatrix();
	Matrix4 projMatrix = cam->getProjectionMatrix();
	Vector4 in = Vector4(objPos.x, objPos.y, objPos.z, 1.0);
	Vector4 out = viewMatrix * in;
#if 1 // method 1: use the existed function provided by Ogre
	out = projMatrix * out;
	out.x /= out.w;
	out.y /= out.w;
	out.z /= out.w;

	if (out.w <= 0.0) return;

	// Map x, y and z to range 0-1
        out.x = out.x * 0.5 + 0.5;
	out.y = out.y * 0.5 + 0.5;
	out.z = out.z * 0.5 + 0.5;

	// Map x,y to viewport
	out.x = out.x * screenRect.x;
	out.y = (1 - out.y) * screenRect.y;

	screenPos.x = out.x;
	screenPos.y = out.y;

#else // Method 2: write the projection myself
         // I don't think this is 100% correct because no camera is at the origin.
	out.x = 236.f * (out.x / out.z);
	out.y = 236.f * (out.y / out.z);

	screenPos.x = -out.x + (screenRect.x / 2.0f);
	screenPos.y = out.y + (screenRect.y / 2.0f);
#endif

	return;
}
Here I used 2 methods. However, both of them returned me a drifted projection. So can I get some help here? Can I know why there's always a shift between the 2 projections? And how can I fix it?

Thank you so much!
You do not have the required permissions to view the files attached to this post.