Казалось бы, это должно быть что-то легкое, но мне просто не везет.
Что я хочу сделать, так это использовать основное движение, чтобы отслеживать, куда направлена камера телефона (для своего рода приложения дополненной реальности). Пользователь наводил телефон на контрольную точку (как если бы фотографировал ее) и нажимал кнопку, чтобы «выровнять» положение телефона с объектом. Теперь, когда пользователь направляет камеру телефона на другие объекты, мне нужно определить изменение высоты телефона (от -90º до +90º) и азимута (от 0º до 360º).
Углы Эйлера, заданные CMAttitude, не кажутся мне нужными. Я попытался кэшировать CMAttitude, полученный, когда пользователь нажимает «выравнивание». Затем, когда пользователь перемещает телефон, я получаю новый CMAttitude и используюmultiByInverseOfAttitude, чтобы определить отличие от эталонного положения.
- (void)checkForMotion {
CMMotionManager *motionMgr = appDelegate.motionMgr;
CMDeviceMotion *deviceMotion = motionMgr.deviceMotion;
CMAttitude *attitude = deviceMotion.attitude;
if (referenceAttitude != nil)
{
[attitude multiplyByInverseOfAttitude: referenceAttitude];
double deltaAlt = attitude.pitch;
double deltaAzm = attitude.roll;
// Do something with deltaAlt and deltaAz
}
else
{
NSLog(@"Getting new referenceAttitude");
self.referenceAttitude = attitude;
}
}
Но это просто не дает нужных результатов. Если телефон держать вертикально (длинной осью вверх) то deltaAlt работает нормально. Пока телефон направлен на горизонт (alt = 0), deltaAzm также правильный. Однако, если телефон направлен, скажем, на 45º в небо, то при перемещении телефона по азимуту меняется и высотная составляющая. Эти два переплетены таким образом, что я не могу понять.
Есть ли какая-то простая математика, которая мне нужна, чтобы разделить их? Опять же, я думаю, что это было бы необходимой необходимостью для приложения дополненной реальности, но я не смог найти никаких примеров, которые делают это.