У меня с трудом отображается движение устройства отображения (слияние датчиков) с поворотом SceneKit node. Предпосылка проблемы заключается в следующем:
У меня есть сфера, и камера расположена внутри сферы, так что геометрический центр сферы и камеры node центр совпадают. То, что я хочу достичь, - это когда я вращаюсь физически вокруг точки, движение должно точно отображаться на камере.
Детали реализации выглядят следующим образом:
У меня есть node, с сферой в качестве геотермии и является дочерним для root node. Я использую слияние датчиков, чтобы получить отношение, и затем преобразуя их в углы Эйлера. Код для этого:
- (SCNVector3)eulerAnglesFromCMQuaternion:(CMQuaternion)q
{
GLKQuaternion gq1 = GLKQuaternionMakeWithAngleAndAxis(GLKMathDegreesToRadians(90), 1, 0, 0);
GLKQuaternion gq2 = GLKQuaternionMake(q.x, q.y, q.z, q.w);
GLKQuaternion qp = GLKQuaternionMultiply(gq1, gq2);
CMQuaternion rq = {.x = qp.x, .y = qp.y, .z = qp.z, .w = qp.w};
CGFloat roll = atan2(-rq.x*rq.z - rq.w*rq.y, .5 - rq.y*rq.y - rq.z*rq.z);
CGFloat pitch = asin(-2*(rq.y*rq.z + rq.w*rq.x));
CGFloat yaw = atan2(rq.x*rq.y - rq.w*rq.z, .5 - rq.x*rq.x - rq.z*rq.z);
return SCNVector3Make(roll, pitch, yaw);
}
Уравнение преобразования от 3D Math Primer для графики и развития игр. Я привык записывать как ссылку, не прочитал ее. Но определенно в моем списке чтения.
Теперь, чтобы имитировать физическое вращение в SceneKit, я вращаю свой node содержащий SCNCamera. Это дочерний элемент rootNode. И я использую .rotation свойство сделать то же самое. Здесь следует отметить, что Теперь поток обновления движений устройства выглядит примерно так:
[self.motionManager startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXArbitraryCorrectedZVertical toQueue:mq withHandler:^(CMDeviceMotion *motion, NSError *error) {
CMAttitude *currentAttitude = motion.attitude;
[SCNTransaction begin];
[SCNTransaction setDisableActions:YES];
SCNVector3 v = [self eulerAnglesFromCMQuaternion:currentAttitude.quaternion];
self.cameraNode.eulerAngles = SCNVector3Make( v.y, -v.x, 0); //SCNVector3Make(roll, yaw, pitch)
[SCNTransaction commit];
}];
Что-то предостережение здесь углы эйлеров различны для устройства и для SceneKit node. Ссылки объясняют их.
И в моем понимании сопоставление между двумя происходит примерно так.
Теперь проблема, с которой я столкнулся, - поворот камеры на 360 градусов до моего физического вращения вокруг точки. Что я пытаюсь выполнить с помощью следующего изображения.
Я сомневаюсь, что преобразование углов кватерниона → Эйлера вызывает ошибку, а математика кватернионов сейчас на моей голове.
Надеюсь, что я предоставил всю информацию, если что-то еще потребуется, я просто рад добавить.