OSG/OSGEarth Как переместить камеру
Я делаю симулятор Drone с OSGEarth. Я никогда не использовал OSG раньше, поэтому у меня есть некоторые проблемы с пониманием камер. Я пытаюсь переместить камеру в определенное место (широта / долгота) с определенным креном, высотой и рысканием в OSG Earth.
Мне нужно иметь несколько камер, поэтому я использую композитный просмотрщик. Но я не понимаю, как двигать конкретную камеру. В настоящее время у меня есть один с EarthManipulator, который работает нормально.
class NovaManipulator : publicosgGA::CameraManipulator {
osg::Matrixd NovaManipulator::getMatrix() const
{
//drone_ is only a struct which contains updated infomations
float roll = drone_->roll(),
pitch = drone_->pitch(),
yaw = drone_->yaw();
auto position = drone_->position();
osg::Vec3d world_position;
position.toWorld(world_position);
cam_view_->setPosition(world_position);
const osg::Vec3d rollAxis(0.0, 1.0, 0.0);
const osg::Vec3d pitchAxis(1.0, 0.0, 0.0);
const osg::Vec3d yawAxis(0.0, 0.0, 1.0);
//if found this code :
// https://stackru.com/questions/32595198/controling-openscenegraph-camera-with-cartesian-coordinates-and-euler-angles
osg::Quat rotationQuat;
rotationQuat.makeRotate(
osg::DegreesToRadians(pitch + 90), pitchAxis,
osg::DegreesToRadians(roll), rollAxis,
osg::DegreesToRadians(yaw), yawAxis);
cam_view_->setAttitude(rotationQuat);
// I don't really understand this also
auto nodePathList = cam_view_->getParentalNodePaths();
return osg::computeLocalToWorld(nodePathList[0]);
}
osg::Matrixd NovaManipulator::getInverseMatrix() const
{
//Don't know why need to be inverted
return osg::Matrix::inverse(getMatrix());
}
};
Затем я устанавливаю манипулятор для просмотра. И когда я симулирую мир, камера на хорошем месте (широта / долгота / высота). Но ориентация совершенно неверна и я не могу найти, где мне нужно "исправить" ось.
На самом деле мой дрон находится во Франции, но вектор "вверх" плох, он все еще направлен на север, а не "вертикально" относительно земли. Посмотрите, что я получаю на правильной камере
Мне нужно иметь рыскание относительно севера (0 ==> Север), и когда мой крен и тангаж установлены на ноль, я должен быть "параллелен" земле.
Является ли мой подход (делая манипулятор) лучшим для этого? Могу ли я поместить объект камеры внутри узла График (за osgEarth::GeoTransform
(это работает для моей модели))?
Спасибо:)
2 ответа
В прошлом я делал симпатичный трюк, включающий использование объекта ObjectLocator (чтобы получить мировое положение и ориентацию плоскости к касательной к поверхности) в сочетании с матрицей для применения HPR. Там есть инвертирование, чтобы превратить его в матрицу ориентации камеры, а не в матрицу размещения объектов, но все работает хорошо.
http://forum.osgearth.org/void-ObjectLocator-setOrientation-default-orientation-td7496768.html
Немного сложно увидеть, что происходит в вашем фрагменте кода, поскольку типы многих переменных не очевидны.
AlphaPixel делает много вещей типа телеметрии / osgEarth, так что кричите, если вам нужна помощь.
Вероятно, это просто порядок ваших вращений - умножение матриц и кватернионов зависит от порядка. Я бы предложил:
- Попробуйте поменять местами тональность в вашем вызове MakeRotate.
- Если это не сработает, установите все повороты, кроме 1, на 0° за раз, убедившись, что каждый из них соответствует ожидаемому, тогда вы можете играть с ордерами (всего 6 возможных ордеров).
- Вы также можете сделать отдельные кватернионы q1, q2, q3, где каждый представляет h, p и r, по отдельности, и умножить их самостоятельно, чтобы контролировать порядок. Это то, что перегрузка MakeRotate, которую вы используете, делает изнутри.
Обычно вы хотите сначала сделать рыскание, затем высоту тона, затем ваш бросок (или вообще пропустить бросок, если хотите), но я не припомню, чтобы osg::quat соединился в pre-mult или post-mult мода, так что это может быть подглядывать.