[1.11] weird getCameraToViewportRay() output

Problems building or running the engine, queries about how to use features etc.
Post Reply
z80
Gnoblar
Posts: 8
Joined: Sun Aug 05, 2018 7:56 am
x 2

[1.11] weird getCameraToViewportRay() output

Post by z80 »

Ogre Version: :1.11:
Operating System: :Ubuntu 16.0:
Render System: :GL3:

Hello! I get very strange output from Ogre::Camera::getCameraToViewportRay(). In particular, I log 1) screen position in pixels, 2) screen relative position and 3) ray direction as an output from getCameraToViewportRay().

The problem is when mouse is smoothly moved ray.getDirection() either remains exactly the same or jumps a lot. Please, see the code and log attached.

Code: Select all

    Ogre::Viewport * v = mCamera->getViewport();
    int left, top, width, height;
    v->getActualDimensions( left, top, width, height );
    const Ogre::Real x = static_cast<Ogre::Real>( mouseAtX - left ) /
            static_cast<Ogre::Real>( width );
    const Ogre::Real y = static_cast<Ogre::Real>( mouseAtY - top ) /
            static_cast<Ogre::Real>( height );

    std::cout << "at: " << mouseAtX << " "
                        << mouseAtY << "   ";

    std::cout << "xy: " << x << " "
                        << y << "   ";

    ray = mCamera->getCameraToViewportRay( x, y );
    Ogre::Vector3 a  = ray.getDirection();

    std::cout << "a_abs: " << a.x << " "
                           << a.y << " "
                           << a.z << std::endl;

Gives the following output:

at: 586 333 xy: 0.572266 0.433594 a_abs: -0.327264 0.930657 -0.163632
at: 585 334 xy: 0.571289 0.434896 a_abs: -0.327264 0.930657 -0.163632
at: 584 334 xy: 0.570312 0.434896 a_abs: -0.327264 0.930657 -0.163632
at: 583 334 xy: 0.569336 0.434896 a_abs: 0 0.984892 -0.173168
at: 582 334 xy: 0.568359 0.434896 a_abs: 0 0.984892 -0.173168
Lax
Hobgoblin
Posts: 583
Joined: Mon Aug 06, 2007 12:53 pm
Location: Saarland, Germany
x 50

Re: [1.11] weird getCameraToViewportRay() output

Post by Lax »

Hi,

I think your borders are wrong. Here a code snipped, how I do it:

Code: Select all

void EditorManager::handleMouseMove(const OIS::MouseEvent& evt)
{
	Ogre::Real x = 0.0f;
	Ogre::Real y = 0.0f;
	mouseToViewPort(evt.state.X.abs, evt.state.Y.abs, x, y, renderWindow);
	Ogre::Ray hitRay = this->camera->getCameraToViewportRay(x, y);
}

void mouseToViewPort(int mx, int my, Ogre::Real& x, Ogre::Real& y, Ogre::RenderWindow* renderWindow)
{
	x = (Ogre::Real)((Ogre::Real)mx / (Ogre::Real)renderWindow->getWidth());
	y = (Ogre::Real)((Ogre::Real)my / (Ogre::Real)renderWindow->getHeight());
}
Best Regards
Lax

http://www.lukas-kalinowski.com/Homepage/?page_id=1631
Please support Second Earth Technic Base built of Lego bricks for Lego ideas: https://ideas.lego.com/projects/81b9bd1 ... b97b79be62

z80
Gnoblar
Posts: 8
Joined: Sun Aug 05, 2018 7:56 am
x 2

Re: [1.11] weird getCameraToViewportRay() output

Post by z80 »

Hi! Thanks for the reply. I really appreciate it. I tried your code and it works exactly the same way.

But I think I now understand the problem better. I copy-pasted the implementation of getCameraToViewportRay() method into my code and printed the output after every single. As far as I can see the problem is in camera Projection matrix.

Code: Select all

Mproj
1.81  0.0     0.0   0.0
0.0    2.41   0.0   0.0
0.0    0.0    -1.0   0.0001999
0.0    0.0    -1.0   0.0
Two bottom rows are almost the same. It means that when I invert it I get very large numbers. And that it exactly what happens here.

Code: Select all

inverted Mproj
0.552   0.0      0.0     0.0
0.0       0.415  0.0     0.0 
0.0       0.0      0.0   -1.0
0.0       0.0     5000  -5000
And due to getCameraToViewportRay() uses Mview^-1 * Mproj^-1 in combination it gives a matrix simultaneously containing lightyears and nanometers :D Which gives this crazy behavior.

My main question is: I didn't apply any explicit efforts to change any camera parameters. I expect camera settings to be default. I just use one of Ogre examples for my test project. Is it really how Projection matrix should look like? And if yes than how does it work for everyone else?

I would appreciate any help! Thank you!
paroj
OGRE Team Member
OGRE Team Member
Posts: 1995
Joined: Sun Mar 30, 2014 2:51 pm
x 1075
Contact:

Re: [1.11] weird getCameraToViewportRay() output

Post by paroj »

try cam.setNearClipDistance(5)
z80
Gnoblar
Posts: 8
Joined: Sun Aug 05, 2018 7:56 am
x 2

Re: [1.11] weird getCameraToViewportRay() output

Post by z80 »

paroj wrote: Fri Jan 11, 2019 12:22 pm try cam.setNearClipDistance(5)
Thank you! That works! It looks like I set my near clipping plane a very small value somewhere in the code or it already was small.

If someone finds it useful I ended up copy-pasting the implementation of getCameraToViewportRay() and overwriting Projection matrix components m[2][2] and m[2][3] with reasonable numbers like -3.0 and -6.0. That code gives the right result regardless of clipping plane settings.

Code: Select all

    Ogre::RenderWindow * w = getRenderWindow();
    Ogre::Real screenX = (Ogre::Real)((Ogre::Real)mouseAtX / (Ogre::Real)w->getWidth());
    Ogre::Real screenY = (Ogre::Real)((Ogre::Real)mouseAtY / (Ogre::Real)w->getHeight());
    std::cout << "f: " << screenX << " "
                       << screenY << std::endl;

    const Ogre::Real Zn = 1.0;
    const Ogre::Real Zf = 2.0;

    Matrix4 mp = mCamera->getProjectionMatrix();
    const Matrix4 mv = mCamera->getViewMatrix(true);

    mp[2][2] = -(Zf+Zn)/(Zf-Zn);
    mp[2][3] = -(Zf*Zn)/(Zf-Zn)*2.0;

    Matrix4 inverseVP = (mp * mv).inverse();

    const Matrix4 & m = inverseVP;
    std::cout << m[0][0] << " " << m[0][1] << " " << m[0][2] << " " << m[0][3] << std::endl;
    std::cout << m[1][0] << " " << m[1][1] << " " << m[1][2] << " " << m[1][3] << std::endl;
    std::cout << m[2][0] << " " << m[2][1] << " " << m[2][2] << " " << m[2][3] << std::endl;
    std::cout << m[3][0] << " " << m[3][1] << " " << m[3][2] << " " << m[3][3] << std::endl;

#if OGRE_NO_VIEWPORT_ORIENTATIONMODE == 0
    // We need to convert screen point to our oriented viewport (temp solution)
    Real tX = screenX; Real a = mCamera->getOrientationMode() * Math::HALF_PI;
    screenX = Math::Cos(a) * (tX-0.5f) + Math::Sin(a) * (screenY-0.5f) + 0.5f;
    screenY = Math::Sin(a) * (tX-0.5f) + Math::Cos(a) * (screenY-0.5f) + 0.5f;
    if ((int)mCamera->getOrientationMode()&1) screenY = 1.f - screenY;
#endif

    Real nx = (2.0f * screenX) - 1.0f;
    Real ny = 1.0f - (2.0f * screenY);
    std::cout << "n: " << nx << " "
                       << ny << std::endl;
    Vector3 nearPoint(nx, ny, -1.f);
    std::cout << "np: " << nearPoint.x << " "
                        << nearPoint.y << " "
                        << nearPoint.z << std::endl;
    // Use midPoint rather than far point to avoid issues with infinite projection
    Vector3 midPoint (nx, ny,  0.0f);
    std::cout << "mp: " << midPoint.x << " "
                        << midPoint.y << " "
                        << midPoint.z << std::endl;

    // Get ray origin and ray target on near plane in world space
    Vector3 rayOrigin, rayTarget;

    rayOrigin = inverseVP * nearPoint;
    std::cout << "ro: " << rayOrigin.x << " "
                        << rayOrigin.y << " "
                        << rayOrigin.z << std::endl;
    rayTarget = inverseVP * midPoint;
    std::cout << "rt: " << rayTarget.x << " "
                        << rayTarget.y << " "
                        << rayTarget.z << std::endl;

    Vector3 rayDirection = rayTarget - rayOrigin;

    std::cout << "d: " << rayDirection.x << " "
                       << rayDirection.y << " "
                       << rayDirection.z << std::endl;
    std::cout << "o: " << rayOrigin.x << " "
                       << rayOrigin.y << " "
                       << rayOrigin.z << std::endl;

    rayDirection.normalise();

    ray.setOrigin( rayOrigin );
    ray.setDirection( rayDirection );
Thanks to everyone again!
Post Reply