2012-12-28 48 views
5

मैं quaternions से 3D मॉडल पर arcball रोटेशन, विशेष रूप से आईओएस पर GLKit प्रयोग करने के लिए एक सरल कार्यान्वयन के लिए देख रहा हूँ। अब तक, मैं निम्नलिखित स्रोतों की जांच की है:Arcball रोटेशन (आईओएस GLKit का प्रयोग करके)

मैं भी here और here से स्रोत कोड और गणित समझने की कोशिश कर रहा हूँ। मैं अपनी वस्तु को घुमा सकता हूं लेकिन यह कुछ कोणों पर चारों ओर कूदता रहता है, इसलिए मुझे डर है कि जिम्बल लॉक खेल रहा है। मैं घूर्णन को नियंत्रित करने के लिए इशारा पहचानकर्ताओं का उपयोग कर रहा हूं (पैन जेस्चर रोल और यॉ को प्रभावित करते हैं, इशारा करते हुए इशारे को पिच प्रभावित करते हैं)। मैं quaternion हैंडलिंग के साथ ही मॉडलव्यू मैट्रिक्स परिवर्तन के लिए अपने कोड संलग्न कर रहा हूँ।

चर:

  • GLKQuaternion rotationE;

Quaternion हैंडलिंग:

- (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)); 
} 

Modelview मैट्रिक्स परिवर्तन (अंदर ड्रा लूप):

// 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); 

किसी भी मदद की बहुत सराहना की जाती है, लेकिन मैं इसे यथासंभव सरल रखना चाहता हूं और जीएलकिट से चिपकना चाहता हूं।

उत्तर

5

यहां कुछ समस्याएं चल रही हैं।

  1. आप कहते हैं कि आप [x, y] पैन के लिए उपयोग कर रहे हैं, लेकिन ऐसा लगता है कि आप उन्हें पिच और यॉ के लिए उपयोग कर रहे हैं। मेरे लिए, कम से कम, पैनिंग अनुवाद है, घूर्णन नहीं।

  2. जब तक मुझे कुछ याद नहीं आ रहा है, तो यह भी लगता है कि जब भी आप इसे अपडेट करने का प्रयास करते हैं तो यह पूरे घूर्णन को बदल देता है। आप वर्तमान रोटेशन के विपरीत से एक वेक्टर घुमाते हैं और फिर उस वेक्टर और कुछ कोण से quaternion बनाते हैं। मेरा मानना ​​है कि यह मूल वेक्टर से quaternion बनाने के लिए बराबर है और फिर वर्तमान रोटेशन उलटा द्वारा घूर्णन। तो आपके पास q_e'*q_up है। फिर आप वर्तमान रोटेशन के साथ गुणा करते हैं, जो q_e*q_e'*q_up = q_up देता है। वर्तमान रोटेशन रद्द कर दिया गया है। ऐसा लगता है कि आप यही चाहते हैं।

    आपको केवल इतना करना है कि अक्ष-और-कोण से एक नया quaternion बनाएं और फिर वर्तमान quaternion के साथ गुणा करें। यदि नया quaternion बाईं ओर है, तो अभिविन्यास परिवर्तन आंखों के स्थानीय फ्रेम का उपयोग करेगा। यदि नया quaternion दाईं ओर है, तो अभिविन्यास परिवर्तन वैश्विक फ्रेम में होगा। मुझे लगता है कि आप चाहते हैं:

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

    यह तीनों मामलों के विपरीत पूर्व-रोटेशन के बिना ऐसा करें।

  3. मैंने कभी भी जीएलकिट का उपयोग नहीं किया है, लेकिन Quaternion से Matrix में कनवर्ट करते समय अक्ष-कोण निकालने के लिए असामान्य है। यदि कोण शून्य है, तो अक्ष अनिर्धारित है। जब यह शून्य के करीब है, तो आपके पास संख्यात्मक अस्थिरता होगी।ऐसा लगता है कि आप GLKMatrix4MakeWithQuaternion का उपयोग करना चाहिए और उसके बाद आपके अनुवाद मैट्रिक्स और बड़े पैमाने मैट्रिक्स के साथ परिणामस्वरूप मैट्रिक्स गुणा:

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

शानदार जवाब देने के लिए डाल दिया आशा है, यह पूरी तरह से काम किया। यह quaternions में मेरा पहला उद्यम है, तो स्पष्ट स्पष्टीकरण की सराहना की है - धन्यवाद! मैंने आपके प्रश्न को (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)); 
} 

आप अच्छा उपयोग :)