непрерывное плавное пошаговое вращение узла (камеры)

Я пытаюсь постепенно повернуть камеру вокруг оси x на 5 градусов. работает нормально кроме анимации на 355 прыгает внезапно. это происходит из-за цепочки анимации. если мой следующий метод вызывается в SCNSceneRendererDelegate, то это не вращение по времени. SCNSceneRendererDelegate срабатывает в каждом кадре. и это означает, что мое действие анимации сцены с продолжительностью еще не готово. уменьшая продолжительность анимации, анимация больше не будет плавной. выполнение таймера с тем же интервалом, что и продолжительность анимации, также выглядит плохо. Есть ли способ сделать эту анимацию гладкой?

-(void) updateCameraRotation
{
     SCNQuaternion oldRotScnQuat = _cameraNode.presentationNode.rotation;
     GLKQuaternion glQuatOldRot = GLKQuaternionMakeWithAngleAndAxis(oldRotScnQuat.w, oldRotScnQuat.x, oldRotScnQuat.y, oldRotScnQuat.z);

     float xan = GLKMathDegreesToRadians(5);
     GLKQuaternion newx = GLKQuaternionIdentity;
     GLKVector3 vec = GLKVector3Normalize(GLKVector3Make(1, 0, 0));
     double result = sinf(xan/2);
     newx = GLKQuaternionMakeWithAngleAndAxis(cosf(xan/2), vec.x *result, vec.y * result, vec.z * result);
     newx = GLKQuaternionNormalize(newx);
     glQuatOldRot = GLKQuaternionMultiply(glQuatOldRot, newx);

     axis = GLKQuaternionAxis(glQuatOldRot);
     angle = GLKQuaternionAngle(glQuatOldRot);


    [_cameraNode runAction:[SCNAction rotateToAxisAngle:SCNVector4Make(axis.x, axis.y, axis.z, angle) duration:1]];
}

person Hashmat Khalil    schedule 02.01.2015    source источник
comment
это правда, что методы делегата вызываются в каждом кадре. Но что вы имеете в виду под этим означает, что мое действие анимации сцены с продолжительностью еще не готово?   -  person mnuages    schedule 02.01.2015
comment
если продолжительность анимации составляет, например, 5 секунд, то в этом 5-секундном делегате запускается 60 таймеров в секунду. поэтому метод вызывается 300 раз во время анимации. и это будет вращение 300 x 5 градусов. так что нехорошо. я пытался отменить предыдущую анимацию, даже удалил действие, но это не помогло.   -  person Hashmat Khalil    schedule 02.01.2015
comment
я думаю, что я делаю что-то не так с углом. это правильный способ держать его вращающимся?   -  person Hashmat Khalil    schedule 02.01.2015
comment
если ваш код работает со скоростью 60 кадров в секунду, возможно, вам не нужна анимация. Или вы можете использовать неявные анимации вместо действий. С неявными анимациями (см. SCNTransaction) анимация будет автоматически создана от текущего значения к новому значению, и нет необходимости отменять предыдущие вызовы.   -  person mnuages    schedule 02.01.2015
comment
60 фпс было просто для примера и на айпаде 2 такого не будет например. Ротация не вечна. он управляется ориентацией устройства и/или виртуальным джойстиком. если пользователь продолжает нажимать кнопку в направлении, оно будет вращать камеру, в противном случае она будет неподвижна.   -  person Hashmat Khalil    schedule 03.01.2015
comment
неявные анимации не повторяются, с ними вы сможете добиться того, чего хотите.   -  person mnuages    schedule 03.01.2015
comment
это тот же эффект.   -  person Hashmat Khalil    schedule 03.01.2015


Ответы (2)


SLERP используется для плавного вращения между двумя известными положениями. Старайтесь избегать ненужных преобразований между углом оси и кватернионами (если возможно, оставьте их в кватернионах). http://www.euclideanspace.com/maths/алгебра/realNormedAlgebra/quaternions/slerp/

Вам также нужно будет рассчитать угол между осями кватерниона: /кватернион-расстояние

Я использовал обе эти функции сам, и они работают хорошо. Вместо того, чтобы добавлять 5 градусов на кадр, вы можете указать скаляр t в диапазоне [0, 1].

Например, при повороте от кватерниона P к Q, R = SLERP(P, Q, t) даст вам кватернион R от P до Q. Если t = 0, то R = P, если t = 1, то R = Q.

person Gouda    schedule 12.01.2015

Попробуйте предоставить CABasicAnimation с byValue, установленным на ваши 5 градусов, и установите бесконечные повторения. Это не сработает?

person Aviad Ben Dov    schedule 07.07.2015