2012-12-28 6 views
5

quaternions가있는 3D 모델에서 arcball 회전을위한 간단한 구현 인 을 찾고 있는데 특히 iOS에서 GLKit을 사용합니다. 지금까지, 나는 다음과 같은 소스를 조사 하였다 : 나는 또한 herehere에서 소스 코드와 수학을 이해하려고 노력했습니다Quaternions로 Arcball 회전 (iOS GLKit 사용)

. 내 물건을 회전시킬 수는 있지만 특정 각도에서 계속 뛰어 다니기 때문에 짐벌 잠금 장치가 작동하는 것이 두렵다. 제스처 인식기를 사용하여 회전을 제어합니다 (팬 동작은 롤과 요에 영향을주고 회전 동작은 피치에 영향을줍니다). 쿼터니언 처리 및 modelview 행렬 변환을위한 코드를 첨부하고 있습니다.

변수 :

  • GLKQuaternion rotationE;

사원 수 처리 :

- (void)rotateWithXY:(float)x and:(float)y 
{ 
    const float rate = M_PI/360.0f; 
    GLKVector3 up = GLKVector3Make(0.0f, 1.0f, 0.0f); 
    GLKVector3 right = GLKVector3Make(1.0f, 0.0f, 0.0f); 

    up = GLKQuaternionRotateVector3(GLKQuaternionInvert(self.rotationE), up); 
    self.rotationE = GLKQuaternionMultiply(self.rotationE, GLKQuaternionMakeWithAngleAndVector3Axis(x*rate, up)); 

    right = GLKQuaternionRotateVector3(GLKQuaternionInvert(self.rotationE), right); 
    self.rotationE = GLKQuaternionMultiply(self.rotationE, GLKQuaternionMakeWithAngleAndVector3Axis(y*rate, right)); 
} 

- (void)rotateWithZ:(float)z 
{ 
    GLKVector3 front = GLKVector3Make(0.0f, 0.0f, -1.0f); 

    front = GLKQuaternionRotateVector3(GLKQuaternionInvert(self.rotationE), front); 
    self.rotationE = GLKQuaternionMultiply(self.rotationE, GLKQuaternionMakeWithAngleAndVector3Axis(z, front)); 
} 

모델 뷰 매트릭스 변환 (내부 그리기 루프) :

// Get Quaternion Rotation 
GLKVector3 rAxis = GLKQuaternionAxis(self.transformations.rotationE); 
float rAngle = GLKQuaternionAngle(self.transformations.rotationE); 

// Set Modelview Matrix 
GLKMatrix4 modelviewMatrix = GLKMatrix4Identity; 
modelviewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -0.55f); 
modelviewMatrix = GLKMatrix4Rotate(modelviewMatrix, rAngle, rAxis.x, rAxis.y, rAxis.z); 
modelviewMatrix = GLKMatrix4Scale(modelviewMatrix, 0.5f, 0.5f, 0.5f); 
glUniformMatrix4fv(self.sunShader.uModelviewMatrix, 1, 0, modelviewMatrix.m); 

어떤 도움을 주셔서 감사합니다,하지만 최대한 간단하게 유지하고 GLKit을 고수하고 싶습니다.

답변

5

여기에 몇 가지 문제가있는 것으로 보입니다.

  1. 당신은 당신이 이동하기 [X, Y]를 사용하고 있다고, 그러나 당신이 피치 및 요 그들을 사용하고 더 많은 것 같습니다. 적어도 패닝은 회전이 아니라 번역입니다.

  2. 내가 뭔가를 놓치지 않는 한, 업데이트 할 때마다 전체 교체를 교체하는 것처럼 보입니다. 현재 회전의 반대 방향으로 벡터를 회전 한 다음 해당 벡터와 각도로 쿼터니온을 만듭니다. 이것은 원래 벡터로부터 쿼터니온을 생성하고 현재의 회전 반전에 의해 쿼터니언을 회전시키는 것과 같습니다. 따라서 당신은 q_e'*q_up입니다. 그런 다음 이것을 현재 회전과 곱하면 q_e*q_e'*q_up = q_up이됩니다. 현재 회전이 취소됩니다. 이것은 당신이 원하는 것처럼 보이지 않습니다.

    축 앤 각도에서 새로운 쿼터니언을 생성 한 다음 현재 쿼터니언으로 곱하면됩니다. 새로운 쿼터니온이 왼쪽에 있으면 방향 변경이 눈 - 로컬 프레임을 사용합니다. 새로운 쿼터니언이 오른쪽에 있으면 오리엔테이션 변경이 전역 프레임에 적용됩니다. 당신이 원하는 것 같아요 :

    self.rotationE = 
        GLKQuaternionMultiply( 
        GLKQuaternionMakeWithAngleAndVector3Axis(x*rate, up),self.rotationE); 
    

    3 가지 경우 모두 반대 방향으로 사전 회전하지 마십시오.

  3. 저는 GLKit을 사용한 적이 없지만 Quaternion에서 Matrix로 변환 할 때 축각을 추출하는 것은 드뭅니다. 각도가 0이면 축이 정의되지 않습니다. 그것이 0에 가까울 때 숫자가 불안정 해집니다.당신이 GLKMatrix4MakeWithQuaternion를 사용하여 다음 번역 매트릭스와 규모 행렬과 결과 행렬을 곱해야한다 같습니다 : 그래서 여기

    GLKMatrix4 modelviewMatrix = 
        GLKMatrix4Multiply(GLKMatrix4MakeTranslation(0.0f, 0.0f, -0.55f), 
             GLKMatrix4MakeWithQuaternion(self.rotationE)); 
    modelviewMatrix = GLKMatrix4Scale(modelviewMatrix, 0.5f, 0.5f, 0.5f); 
    
+0

브릴리언트 대답에 넣어 희망, 완벽하게 일했다. 이것은 쿼터니언으로의 첫 벤처이기 때문에 명확한 설명을 매우 높이 평가합니다. - 감사합니다! 제스처가 "팬"(iOS 대회)으로 지정되었지만 (1)에서 제기 한 요점을 명확히하기 위해 제 질문을 편집했습니다. 실제로는 제 모델의 회전을 제어합니다. –

3

나는 최근에이 문제의 내 결과 구현에 대해 좀 더 질문을 받았다 그것 입니다!

- (void)rotate:(GLKVector3)r 
{ 
    // Convert degrees to radians for maths calculations 
    r.x = GLKMathDegreesToRadians(r.x); 
    r.y = GLKMathDegreesToRadians(r.y); 
    r.z = GLKMathDegreesToRadians(r.z); 

    // Axis Vectors w/ Direction (x=right, y=up, z=front) 
    // In OpenGL, negative z values go "into" the screen. In GLKit, positive z values go "into" the screen. 
    GLKVector3 right = GLKVector3Make(1.0f, 0.0f, 0.0f); 
    GLKVector3 up = GLKVector3Make(0.0f, 1.0f, 0.0f); 
    GLKVector3 front = GLKVector3Make(0.0f, 0.0f, 1.0f); 

    // Quaternion w/ Angle and Vector 
    // Positive angles are counter-clockwise, so convert to negative for a clockwise rotation 
    GLKQuaternion q = GLKQuaternionIdentity; 
    q = GLKQuaternionMultiply(GLKQuaternionMakeWithAngleAndVector3Axis(-r.x, right), q); 
    q = GLKQuaternionMultiply(GLKQuaternionMakeWithAngleAndVector3Axis(-r.y, up), q); 
    q = GLKQuaternionMultiply(GLKQuaternionMakeWithAngleAndVector3Axis(-r.z, front), q); 

    // ModelView Matrix 
    GLKMatrix4 modelViewMatrix = GLKMatrix4Identity; 
    modelViewMatrix = GLKMatrix4Multiply(modelViewMatrix, GLKMatrix4MakeWithQuaternion(q)); 
} 

당신이 잘 사용 :