getting camera to look towards the horizon and rotate around y-axis

classic Classic list List threaded Threaded
6 messages Options
bpattison bpattison
Reply | Threaded
Open this post in threaded view
|

getting camera to look towards the horizon and rotate around y-axis

Our team has been working on HorizonManipulator which positions a camera at a given (lat,lon,height) and looks towards the horizon with a given heading. Its kinda like a "street view" of the surrounding terrain.

Unfortunately, we've not be able to work out the 3D math to get keep the camera from "rolling-over" from the horizon. Any idea what we are missing in our code to keep the camera up-right and always looking at the horizon as the heading changes?

void HorizonManipulator::setCameraPosition(double xLon, double yLat, double zHeight, double heading)
{
  auto const spatialReference = osgEarth::SpatialReference::get("WGS84");
  osgEarth::GeoPoint const geoPoint(spatialReference, xLon, yLat, zHeight);

  osg::Vec3d world;
  geoPoint.toWorld(world);

  auto const r90 = osg::DegreesToRadians(90.0);
  auto const rhdg = osg::DegreesToRadians(heading);
  auto const q =
    osg::Quat(0.0,   osg::Vec3(0, 1,  0)) *
    osg::Quat(r90,   osg::Vec3(1, 0,  0)) *
    osg::Quat(rhdg, osg::Vec3(0, 0, -1));

  setTransformation(world, q);
}


gwaldron gwaldron
Reply | Threaded
Open this post in threaded view
|

Re: getting camera to look towards the horizon and rotate around y-axis

Brian,
What does setTransformation do?
Glenn Waldron / Pelican Mapping
bpattison bpattison
Reply | Threaded
Open this post in threaded view
|

Re: getting camera to look towards the horizon and rotate around y-axis

Sorry, I forgot to mention that the HorizonManipulator is derived from osgGA::FirstPersonManipulator

class HorizonManipulator : public osgGA::FirstPersonManipulator

setTransformation is the osgGA::FirstPersonManipulator::setTransformation() function which sets the manipulator by eye position and eye orientation.

virtual void setTransformation(const osg::Vec3d &eye, const osg::Quat &rotation)

The eye position is correct, but we've been unable to get eye orientation to work properly at all headings. My guess is that we need to compute the eye rotation along the tangent axis to the horizon, but we haven't quite figured it out.

Also it's a Manipulator in name only. We lock down all controls so the user actually won't be able to interact with the map. This works well for our application. So it's not really a general purpose HorizonManipulator which would be awesome to have.

I hope its just some basic 3D math which we are not strong in. Any assistance would be greatly appreciated!

-brian
gwaldron gwaldron
Reply | Threaded
Open this post in threaded view
|

Re: getting camera to look towards the horizon and rotate around y-axis

Assuming you're using a geocentric map, your rotation is relative to a local tangent plane -- but you have not established one. You can do so by calling GeoPoint::createLocalToWorld() and then multiplying that matrix by your quaternion-based rotation. You may also need to customize/replace FPM's setTransformation method to do this.
Glenn Waldron / Pelican Mapping
bpattison bpattison
Reply | Threaded
Open this post in threaded view
|

Re: getting camera to look towards the horizon and rotate around y-axis

Adding in geoPoint.createLocalToWorld() improved camera orientation a lot. Thank you.

But the camera still makes a figure eight pattern relative to the horizon as the heading changes. When heading is 0.0 the camera is positioned properly, otherwise it leans.  I've tried changing the order of the multiplication of the Quat, but with little success. The order below seems to work best. So I am definitely missing something else.

  osg::Matrix m;
  geoPoint.createLocalToWorld(m);

  auto const r = m.getRotate();
  auto const t = m.getTrans();

  auto const r90  = osg::DegreesToRadians(90.0);       // pitch to horizon
  auto const rhdg = osg::DegreesToRadians(heading); // heading from north
  auto const q =
    osg::Quat(0.0,  osg::Vec3(0, 1,  0)) *
    osg::Quat(r90,  osg::Vec3(1, 0,  0)) *
    osg::Quat(rhdg, osg::Vec3(0, 0, -1));

  setTransformation(t, q * r);
bpattison bpattison
Reply | Threaded
Open this post in threaded view
|

Re: getting camera to look towards the horizon and rotate around y-axis

As Jason discovered, the FirstPersonManipluator's VerticalAxisFixed flag was override rotation matrix with its own cause the camera to tilt from the horizon.

Calling setVerticalAxisFixed(false); fixed up the issue and the code now works.

Thanks for finding that issue!