ios Quaternions के साथ Arcball रोटेशन(आईओएस GLKit का प्रयोग करते हुए)




opengl-es (2)

हाल ही में मुझे इस समस्या के अपने कार्यान्वयन के बारे में थोड़ा और पूछा गया था, इसलिए यह यहाँ है!

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

आप इसे अच्छा उपयोग करने के लिए डाल उम्मीद है :)

मैं चतुष्कोणों के साथ 3 डी मॉडल पर arcball रोटेशन के लिए एक साधारण कार्यान्वयन की तलाश कर रहा हूं, विशेषकर IOS पर GLKit का उपयोग कर रहा हूं । अब तक, मैंने निम्नलिखित स्रोतों की जांच की है:

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

चर:

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

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

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

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


यहां कुछ मुद्दे सामने आ रहे हैं।

  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. मैंने कभी GLKit का इस्तेमाल नहीं किया है, लेकिन Quaternion से मैट्रिक्स में परिवर्तित करते समय अक्ष-कोण को निकालना असामान्य है यदि कोण शून्य है, तो अक्ष अनिर्धारित है। जब यह शून्य के पास है, तो आपके पास संख्यात्मक अस्थिरता होगी ऐसा लगता है कि आपको GLKMatrix4MakeWithQuaternion का उपयोग करना चाहिए और फिर परिणामी मैट्रिक्स को अपने अनुवाद मैट्रिक्स और स्केल मैट्रिक्स के साथ गुणा करना चाहिए:

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